<!DOCTYPE html>



  


<html class="theme-next mist use-motion" lang="zh-Hans">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />







<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css" />


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="Hexo, NexT" />










<meta property="og:type" content="website">
<meta property="og:title" content="kyssion-blog">
<meta property="og:url" content="http://yoursite.com/page/2/index.html">
<meta property="og:site_name" content="kyssion-blog">
<meta property="og:locale" content="zh-Hans">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="kyssion-blog">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Mist',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://yoursite.com/page/2/"/>





  <title>kyssion-blog</title>
  








</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left 
  page-home">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/"  class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">kyssion-blog</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/about/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br />
            
            关于
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
            
            标签
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br />
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            归档
          </a>
        </li>
      
        
        <li class="menu-item menu-item-schedule">
          <a href="/schedule/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-calendar"></i> <br />
            
            日程表
          </a>
        </li>
      
        
        <li class="menu-item menu-item-sitemap">
          <a href="/sitemap.xml" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-sitemap"></i> <br />
            
            站点地图
          </a>
        </li>
      
        
        <li class="menu-item menu-item-commonweal">
          <a href="/404/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-heartbeat"></i> <br />
            
            公益404
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            
  <section id="posts" class="posts-expand">
    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2018/10/09/深入理解mybatis（八）mybatis反射层设计/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="kyssion">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="kyssion-blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2018/10/09/深入理解mybatis（八）mybatis反射层设计/" itemprop="url">未命名</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-10-09T15:22:37+08:00">
                2018-10-09
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h3 id="mybatis-整体反射框架设计"><a href="#mybatis-整体反射框架设计" class="headerlink" title="mybatis 整体反射框架设计"></a>mybatis 整体反射框架设计</h3><p><img src="blogimg/mybatis/1.png" alt=""></p>
<p>可以看到，Mybatis对这一块抽象的比较复杂，我们可以看到有几个比较主要的部分：Reflector、Invoker、PropertyTokenizer、MetaClass，MetaObject和ObjectWrapper，下面我们一个一个解析这几个部分，最后合并在一起看看他们是如何协作工作的。</p>
<h3 id="Reflector"><a href="#Reflector" class="headerlink" title="Reflector"></a>Reflector</h3><p>我对Reflector的理解是 Reflector是对类的描述 ，我们从一段UT开始（代码位于ReflectorTest）：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">static</span> <span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">AbstractEntity</span> <span class="keyword">implements</span> <span class="title">Entity</span>&lt;<span class="title">Long</span>&gt; </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> Long id;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Long <span class="title">getId</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> id;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setId</span><span class="params">(Long id)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.id = id;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">Section</span> <span class="keyword">extends</span> <span class="title">AbstractEntity</span> <span class="keyword">implements</span> <span class="title">Entity</span>&lt;<span class="title">Long</span>&gt; </span>&#123;</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testGetSetterType</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">    ReflectorFactory reflectorFactory = <span class="keyword">new</span> DefaultReflectorFactory();</span><br><span class="line">    Reflector reflector = reflectorFactory.findForClass(Section.class);</span><br><span class="line">    Assert.assertEquals(Long.class, reflector.getSetterType(<span class="string">"id"</span>));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这个测试方法首先创建了个ReflectorFactory对象，然后用这个factory创建了一个Section类的Reflector，然后判断Section类中id的setter方法是Long类型的。</p>
<p>ReflectorFactory是对Reflector做的一个简单的工厂，提供类反射的缓存（所以反射这块的开销基本上可以不计了，既灵活又快捷）</p>
<p>DefaultReflectorFactory 是 Reflector的默认实现类，用一个ConcurrentMap缓存所有的Reflector示例，它的findForClass方法如下，它首先尝试从map中获取Reflector，获取失败调用Reflector的构造方法创建示例，缓存并返回：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">static</span> <span class="class"><span class="keyword">interface</span> <span class="title">Entity</span>&lt;<span class="title">T</span>&gt; </span>&#123;</span><br><span class="line">    <span class="function">T <span class="title">getId</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">setId</span><span class="params">(T id)</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> Reflector <span class="title">findForClass</span><span class="params">(Class&lt;?&gt; type)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (classCacheEnabled) &#123;</span><br><span class="line">        <span class="comment">// synchronized (type) removed see issue #461</span></span><br><span class="line">        Reflector cached = reflectorMap.get(type);</span><br><span class="line">        <span class="keyword">if</span> (cached == <span class="keyword">null</span>) &#123;</span><br><span class="line">            cached = <span class="keyword">new</span> Reflector(type);</span><br><span class="line">            reflectorMap.put(type, cached);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> cached;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> Reflector(type);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>之后是Reflector的构造方法：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="title">Reflector</span><span class="params">(Class&lt;?&gt; clazz)</span> </span>&#123;</span><br><span class="line">    type = clazz;</span><br><span class="line">    addDefaultConstructor(clazz);</span><br><span class="line">    addGetMethods(clazz);</span><br><span class="line">    addSetMethods(clazz);</span><br><span class="line">    addFields(clazz);</span><br><span class="line">    readablePropertyNames = getMethods.keySet().toArray(<span class="keyword">new</span> String[getMethods.keySet().size()]);</span><br><span class="line">    writeablePropertyNames = setMethods.keySet().toArray(<span class="keyword">new</span> String[setMethods.keySet().size()]);</span><br><span class="line">    <span class="keyword">for</span> (String propName : readablePropertyNames) &#123;</span><br><span class="line">        caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> (String propName : writeablePropertyNames) &#123;</span><br><span class="line">        caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这一块不再细细展开，方法名见名知义，首先将type成员设置为原始的class对象，之后获取class的构造方法，getter/setter属性，成员字段，之后将属性名转大写存放到caseInsensitivePropertyMap中，为了后面的查找，大小写不敏感。</p>
<p>Reflector的其他方法就是对我们保存的这些类的描述做查找， 其中有两个特别的，也就是我们接下来要讨论的 getSetInvoker和 getGetInvoker</p>
<h3 id="Invoker"><a href="#Invoker" class="headerlink" title="Invoker"></a>Invoker</h3><p>Invoker，顾名思义，就是调用，可以调用的东西，他有一个invoke方法，意思就是调用，参数是target和args，就是调用的对象和调用的参数。</p>
<p>我们来看下它的几个实现类：</p>
<ul>
<li>MethodInvoker: 方法调用</li>
<li>SetFieldInvoker：Setter方法调用</li>
<li>GetFieldInvoker：Getter方法调用<br>MethodInvoker中invoke方法的实现：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> Object <span class="title">invoke</span><span class="params">(Object target, Object[] args)</span> <span class="keyword">throws</span> IllegalAccessException, InvocationTargetException </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> method.invoke(target, args);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>就是简单的method.invoke</p>
<h3 id="PropertyTokenizer"><a href="#PropertyTokenizer" class="headerlink" title="PropertyTokenizer"></a>PropertyTokenizer</h3><p>这个就比较牛逼了，他可以处理属性表达式，PropertyTokenizer还实现了Iterator接口，这意味着他可以处理复杂的嵌套属性</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">hasNext</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> children != <span class="keyword">null</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> PropertyTokenizer <span class="title">next</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> PropertyTokenizer(children);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>字段的含义，name表示当前对象的名字，indexedName是当前对象的名字加上后面的索引（[]）如果有的话，index是索引下标，children是延伸属性（子对象）<br>比如：用PropertyTokenizer去解析 “richType.richList[0].value”，那么 name=richType, indexedName=richType，index=null，children=richList[0].value<br>之后执行tokenizer.next()得到新的tokenizer，此时 name=richList, indexdName=richList[0],index=0, children=value<br>之后我们会结合MetaClass和MetaObject看看他有多牛逼</p>
<h3 id="MetaClass"><a href="#MetaClass" class="headerlink" title="MetaClass"></a>MetaClass</h3><p>MetaClass实际上是对Reflector和ProeprtyTokenizer的一种结合，是我们可以用复杂的属性表达式来获取类型的描述。</p>
<p>同样的，我们结合UT来看看它是怎样工作的，首先是一个示例的复杂类型 RichType</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RichType</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> RichType richType;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String richField;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String richProperty;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> Map richMap = <span class="keyword">new</span> HashMap();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> List richList = <span class="keyword">new</span> ArrayList() &#123;</span><br><span class="line">        &#123;</span><br><span class="line">            add(<span class="string">"bar"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> RichType <span class="title">getRichType</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> richType;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setRichType</span><span class="params">(RichType richType)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.richType = richType;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">getRichProperty</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> richProperty;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setRichProperty</span><span class="params">(String richProperty)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.richProperty = richProperty;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> List <span class="title">getRichList</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> richList;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setRichList</span><span class="params">(List richList)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.richList = richList;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Map <span class="title">getRichMap</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> richMap;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setRichMap</span><span class="params">(Map richMap)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.richMap = richMap;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">shouldCheckGetterExistance</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    ReflectorFactory reflectorFactory = <span class="keyword">new</span> DefaultReflectorFactory();</span><br><span class="line">    MetaClass meta = MetaClass.forClass(RichType.class, reflectorFactory);</span><br><span class="line">    assertTrue(meta.hasGetter(<span class="string">"richField"</span>));</span><br><span class="line">    assertTrue(meta.hasGetter(<span class="string">"richProperty"</span>));</span><br><span class="line">    assertTrue(meta.hasGetter(<span class="string">"richList"</span>));</span><br><span class="line">    assertTrue(meta.hasGetter(<span class="string">"richMap"</span>));</span><br><span class="line">    assertTrue(meta.hasGetter(<span class="string">"richList[0]"</span>));</span><br><span class="line"></span><br><span class="line">    assertTrue(meta.hasGetter(<span class="string">"richType"</span>));</span><br><span class="line">    assertTrue(meta.hasGetter(<span class="string">"richType.richField"</span>));</span><br><span class="line">    assertTrue(meta.hasGetter(<span class="string">"richType.richProperty"</span>));</span><br><span class="line">    assertTrue(meta.hasGetter(<span class="string">"richType.richList"</span>));</span><br><span class="line">    assertTrue(meta.hasGetter(<span class="string">"richType.richMap"</span>));</span><br><span class="line">    assertTrue(meta.hasGetter(<span class="string">"richType.richList[0]"</span>));</span><br><span class="line"></span><br><span class="line">    assertFalse(meta.hasGetter(<span class="string">"[0]"</span>));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这段代码说明了metaClass.hasGetter方法可以接受一个复杂的属性表达式来找到对应的类型描述（利用PropertyTokenizer），这个神奇的功能是这么实现的：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">hasGetter</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">    PropertyTokenizer prop = <span class="keyword">new</span> PropertyTokenizer(name);</span><br><span class="line">    <span class="keyword">if</span> (prop.hasNext()) &#123;</span><br><span class="line">        <span class="keyword">if</span> (reflector.hasGetter(prop.getName())) &#123;</span><br><span class="line">            MetaClass metaProp = metaClassForProperty(prop);</span><br><span class="line">            <span class="keyword">return</span> metaProp.hasGetter(prop.getChildren());</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> reflector.hasGetter(prop.getName());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>首先检查tokenizer的name字段对应的属性是不是有getter方法，之后迭代子属性，直到最后，children为空。</p>
<p>MetaClass中的还有几个方法的实现和这个类似，hasSetter, getGetterType, getSetterType</p>
<p>以上都是类级别的反射抽象，下面看看对象级别的</p>
<h3 id="ObjectWrapper"><a href="#ObjectWrapper" class="headerlink" title="ObjectWrapper"></a>ObjectWrapper</h3><p>ObjectWrapper是对对象的描述的抽象，它抽象出一系列对对象描述的查询和更新的接口</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">ObjectWrapper</span> </span>&#123;</span><br><span class="line">    <span class="function">Object <span class="title">get</span><span class="params">(PropertyTokenizer prop)</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">set</span><span class="params">(PropertyTokenizer prop, Object value)</span></span>;</span><br><span class="line">    <span class="function">String <span class="title">findProperty</span><span class="params">(String name, <span class="keyword">boolean</span> useCamelCaseMapping)</span></span>;</span><br><span class="line">    String[] getGetterNames();</span><br><span class="line">    String[] getSetterNames();</span><br><span class="line">    Class&lt;?&gt; getSetterType(String name);</span><br><span class="line">    Class&lt;?&gt; getGetterType(String name);</span><br><span class="line">    <span class="function"><span class="keyword">boolean</span> <span class="title">hasSetter</span><span class="params">(String name)</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">boolean</span> <span class="title">hasGetter</span><span class="params">(String name)</span></span>;</span><br><span class="line">    <span class="function">MetaObject <span class="title">instantiatePropertyValue</span><span class="params">(String name, PropertyTokenizer prop, ObjectFactory objectFactory)</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">boolean</span> <span class="title">isCollection</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">add</span><span class="params">(Object element)</span></span>;</span><br><span class="line">    &lt;E&gt; <span class="function"><span class="keyword">void</span> <span class="title">addAll</span><span class="params">(List&lt;E&gt; element)</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>ObjectWrapper有个几个实现类</p>
<ul>
<li>BeanWrapper，包装Javabean的描述，</li>
<li>MapWrapper，包装Map（键值对）的描述</li>
<li>CollectionWrapper，包装Collection（集合）的描述</li>
<li>ObjectWrapperFactory 了操作实例化ObjectWrapper的工厂方法的抽象，可自定义实现</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> Object <span class="title">getBeanProperty</span><span class="params">(PropertyTokenizer prop, Object object)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        Invoker method = metaClass.getGetInvoker(prop.getName());</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> method.invoke(object, NO_ARGUMENTS);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Throwable t) &#123;</span><br><span class="line">            <span class="keyword">throw</span> ExceptionUtil.unwrapThrowable(t);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">catch</span> (RuntimeException e) &#123;</span><br><span class="line">        <span class="keyword">throw</span> e;</span><br><span class="line">    &#125; <span class="keyword">catch</span> (Throwable t) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> ReflectionException(<span class="string">"Could not get property '"</span> + prop.getName() + <span class="string">"' from "</span> + object.getClass() + <span class="string">".  Cause: "</span> + t.toString(), t);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">setBeanProperty</span><span class="params">(PropertyTokenizer prop, Object object, Object value)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        Invoker method = metaClass.getSetInvoker(prop.getName());</span><br><span class="line">        Object[] params = &#123;value&#125;;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            method.invoke(object, params);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Throwable t) &#123;</span><br><span class="line">            <span class="keyword">throw</span> ExceptionUtil.unwrapThrowable(t);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">catch</span> (Throwable t) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> ReflectionException(<span class="string">"Could not set property '"</span> + prop.getName() + <span class="string">"' of '"</span> + object.getClass() + <span class="string">"' with value '"</span> + value + <span class="string">"' Cause: "</span> + t.toString(), t);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="MetaObject"><a href="#MetaObject" class="headerlink" title="MetaObject"></a>MetaObject</h3><p>MetaObject也是对对象的描述，它代理了objectWrapper的大部分方法，和MetaClass一样，它利用PropertyTokenizer做了对复杂属性表达式的处理</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">shouldGetAndSetNestedField</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    RichType rich = <span class="keyword">new</span> RichType();</span><br><span class="line">    MetaObject meta = SystemMetaObject.forObject(rich);</span><br><span class="line">    meta.setValue(<span class="string">"richType.richField"</span>, <span class="string">"foo"</span>);</span><br><span class="line">    assertEquals(<span class="string">"foo"</span>, meta.getValue(<span class="string">"richType.richField"</span>));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>MetaObject有5个成员字段，</p>
<ul>
<li>originalObject：原始对象，</li>
<li>objectWrapper，被包装的objectWrapper，</li>
<li>objectFactory，对象创建工厂，用于在setValue方法中创建不存在的对象属性实例，</li>
<li>objectWrapperFactory，创建特定的objectWrapper，</li>
<li>reflectorFactory，用来自定一反射类生成的，如果需要可以自行的扩展</li>
</ul>
<h3 id="协作"><a href="#协作" class="headerlink" title="协作"></a>协作</h3><p>反射层的类互相协作，最终根据入参制作出来一个完美的MetaObject和MetaClass给其他组件使用，这其中，比较重要的方法有：</p>
<p>Configuration.newMetaObject，根据传入的object和配置的factory创建对象描述</p>
<p>实际上，ObjectFactory，ObjectWrapperFactory，ReflectorFactory是可以在XML中配置成自定义的，工厂对象全局单例（Configuration对象中）</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">parseConfiguration</span><span class="params">(XNode root)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">//issue #117 read properties first</span></span><br><span class="line">        propertiesElement(root.evalNode(<span class="string">"properties"</span>));</span><br><span class="line">        Properties settings = settingsAsProperties(root.evalNode(<span class="string">"settings"</span>));</span><br><span class="line">        loadCustomVfs(settings);</span><br><span class="line">        typeAliasesElement(root.evalNode(<span class="string">"typeAliases"</span>));</span><br><span class="line">        pluginElement(root.evalNode(<span class="string">"plugins"</span>));</span><br><span class="line">        objectFactoryElement(root.evalNode(<span class="string">"objectFactory"</span>));</span><br><span class="line">        objectWrapperFactoryElement(root.evalNode(<span class="string">"objectWrapperFactory"</span>));</span><br><span class="line">        reflectorFactoryElement(root.evalNode(<span class="string">"reflectorFactory"</span>));</span><br><span class="line">        settingsElement(settings);</span><br><span class="line">        <span class="comment">// read it after objectFactory and objectWrapperFactory issue #631</span></span><br><span class="line">        environmentsElement(root.evalNode(<span class="string">"environments"</span>));</span><br><span class="line">        databaseIdProviderElement(root.evalNode(<span class="string">"databaseIdProvider"</span>));</span><br><span class="line">        typeHandlerElement(root.evalNode(<span class="string">"typeHandlers"</span>));</span><br><span class="line">        mapperElement(root.evalNode(<span class="string">"mappers"</span>));</span><br><span class="line">    &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> BuilderException(<span class="string">"Error parsing SQL Mapper Configuration. Cause: "</span> + e, e);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>XMlConfigBuilder.settingsAsProperties方法使用MetaClass检查Properties参数有没有非法的key</p>
<p>MetaObject和MetaClass在Session的执行周期（executor, mapping, builder…）中还具有广泛的应用</p>

          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2018/10/09/英语学习/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="kyssion">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="kyssion-blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2018/10/09/英语学习/" itemprop="url">未命名</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-10-09T15:22:37+08:00">
                2018-10-09
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <p>Resolvable 可分解 dependentResoulvable 可分解依赖<br>Definition 定义<br>condition 条件<br>Alias 别名<br>Capable 能够能力才敢<br>Check 检查,审核<br>existing 现有<br>Holder 持有人<br>Hierarchical 分级<br>reference  参考<br>guide 指南<br>provide 提供<br>detailed 详细<br>comprehensive 全面的<br>features 特征<br>underlying 底层<br>as well as 以及<br>concepts 概念<br>embraced 拥抱<br>favors convention over configuration 趋向习惯否决配置<br>as quickly as possible 尽快<br>get you up 尽快的运作<br>task focused 专注于任务<br>comprehensive  全方面的<br>infrastructure 基础的<br>Spring handles the infrastructure spring 处理底层架构<br>focus on 专注<br>non-invasively 非侵入性<br>capability  能力<br>applies to 适用于<br>benefit 效益 can benefit from  从中受益<br>execute  执行<br>platform 平台<br>application-specific 专用<br>identifies  识别<br>specified  规定<br>processes 流程<br>in order to 为累<br>performance 性能<br>particularly 特别<br>intuitive 直观<br>hierarchy 等级<br>designator 代号<br>proxy-based 基于代理<br>Declarative 陈述<br>transaction 交易<br>option  选项<br>impact on  碰撞 on 影响<br>programmatic<br>access 访问<br>In addition to 除了<br>persistence  坚持<br>non-recoverable 不可恢复<br>handle 处理<br>converted to 转换成<br>among 介词 several 形容词 approaches 名词 其中一些方法<br>optimize 优化<br>still mix 仍然混合<br>match to 匹配<br>feature 特征<br>popular 流行<br>This “lowest level” approach and all others use a JdbcTemplate under the covers. 这种方法是其他的各种方法的最低基础<br>placeholders 占位符<br>sub-class 子类<br>various 各个<br>as opposed to 而不是<br>oppese to 反对<br>delegates to 委托代表<br>Notice 注意<br>notation 符号<br>corresponding 相应的<br>Alternatively 另外的<br>implemented 实施<br>agnostic 不可知<br>covers 盖子<br>Individual 个别<br>chapters 章节<br>Introduction 介绍<br>original 原版的<br>formal 正式的名称<br>while 介词而<br>declared 声明<br>discover 发现<br>delegate 委托代表<br>components 组件<br>sequence 序列<br>extension 延期<br>execution chain执行链<br>resolvers 解析器<br>declaring 声明<br>specity ordering指定顺序<br>contract 合同<br>specifies 指定<br>indicate 表明<br>in the case of如果是<br>figure 数字<br>overall 总体<br>dedicated 专用<br>perform  演出<br>recognize 识别<br>@ResqusetHeader<br>@ReatController<br>detection 发现<br>stereotype 铅版模板<br>detecting 检查<br>typically 选择<br>various 各个<br>express 表现<br>narrow down 缩小范围<br>a specific endpoint 特定的终点<br>generally recommend 通常推荐<br>candidate  候选人<br>currently 目前<br>representation 表现<br>plays a specific role 体现出特别的角色<br>assumes 假设<br>sets up 设置<br>directly tied. 直接绑定<br>pick 挑选<br>convention 惯例<br>entry point. 入口点<br>delegates 代表<br>as an argument 作为一个论据<br>have a useful run goal  拥有一个可运行的目标<br>third party libraries.  第三方库<br>manually 手动</p>
<p>“wordgoodgoodgoodbestword”<br>[“word”,”good”,”best”,”good”]’</p>

          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2018/10/09/深入理解mybatis（十）mybatis插件和底层实现原理/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="kyssion">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="kyssion-blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2018/10/09/深入理解mybatis（十）mybatis插件和底层实现原理/" itemprop="url">未命名</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-10-09T15:22:37+08:00">
                2018-10-09
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h2 id="深入理解mybatis（六）mybatis插件和底层实现原理"><a href="#深入理解mybatis（六）mybatis插件和底层实现原理" class="headerlink" title="深入理解mybatis（六）mybatis插件和底层实现原理"></a>深入理解mybatis（六）mybatis插件和底层实现原理</h2><h3 id="插件（plugins）"><a href="#插件（plugins）" class="headerlink" title="插件（plugins）"></a>插件（plugins）</h3><p>MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下，MyBatis 允许使用插件来拦截的方法调用包括：</p>
<ul>
<li>Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)</li>
<li>ParameterHandler (getParameterObject, setParameters)</li>
<li>ResultSetHandler (handleResultSets, handleOutputParameters)</li>
<li>StatementHandler (prepare, parameterize, batch, update, query)</li>
</ul>
<p>这些类中方法的细节可以通过查看每个方法的签名来发现，或者直接查看 MyBatis 的发行包中的源代码。 假设你想做的不仅仅是监控方法的调用，那么你应该很好的了解正在重写的方法的行为。 因为如果在试图修改或重写已有方法的行为的时候，你很可能在破坏 MyBatis 的核心模块。 这些都是更低层的类和方法，所以使用插件的时候要特别当心。</p>
<p>通过 MyBatis 提供的强大机制，使用插件是非常简单的，只需实现 Interceptor 接口，并指定了想要拦截的方法签名即可。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// ExamplePlugin.java</span></span><br><span class="line"><span class="meta">@Intercepts</span>(&#123;<span class="meta">@Signature</span>(</span><br><span class="line">  type= Executor.class,</span><br><span class="line">  method = <span class="string">"update"</span>,</span><br><span class="line">  args = &#123;MappedStatement.class,Object.class&#125;)&#125;)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ExamplePlugin</span> <span class="keyword">implements</span> <span class="title">Interceptor</span> </span>&#123;</span><br><span class="line">  <span class="function"><span class="keyword">public</span> Object <span class="title">intercept</span><span class="params">(Invocation invocation)</span> <span class="keyword">throws</span> Throwable </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> invocation.proceed();</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="function"><span class="keyword">public</span> Object <span class="title">plugin</span><span class="params">(Object target)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> Plugin.wrap(target, <span class="keyword">this</span>);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setProperties</span><span class="params">(Properties properties)</span> </span>&#123;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- mybatis-config.xml --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">plugins</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">plugin</span> <span class="attr">interceptor</span>=<span class="string">"org.mybatis.example.ExamplePlugin"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"someProperty"</span> <span class="attr">value</span>=<span class="string">"100"</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">plugins</span>&gt;</span></span><br></pre></td></tr></table></figure>

          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2018/10/09/深入分析spring的装箱扩展/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="kyssion">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="kyssion-blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2018/10/09/深入分析spring的装箱扩展/" itemprop="url">未命名</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-10-09T15:22:37+08:00">
                2018-10-09
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <ol>
<li>BeanPostProcessor</li>
</ol>

          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2018/10/09/深入理解mybatis（五）java api/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="kyssion">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="kyssion-blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2018/10/09/深入理解mybatis（五）java api/" itemprop="url">未命名</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-10-09T15:22:37+08:00">
                2018-10-09
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h2 id="深入理解mybatis（五）java-api"><a href="#深入理解mybatis（五）java-api" class="headerlink" title="深入理解mybatis（五）java api"></a>深入理解mybatis（五）java api</h2><h3 id="SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession"><a href="#SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession" class="headerlink" title="SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession"></a>SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession</h3><p>可以说每个MyBatis都是以一个SqlSessionFactory实例为中心的。SqlSessionFactory实例可以通过SqlSessionFactoryBuilder来构建。一是可以通过XML配置文件的方式来构建SqlSessionFactory，二是可以通过Java API的方式来构建。但不管通过什么方式都有一个Configuration贯穿始终，各种配置正是通过Configuration实例来完成实现。</p>
<h4 id="sqlSessionfactoryBuiler生成SqlSessionFactory的方法"><a href="#sqlSessionfactoryBuiler生成SqlSessionFactory的方法" class="headerlink" title="sqlSessionfactoryBuiler生成SqlSessionFactory的方法"></a>sqlSessionfactoryBuiler生成SqlSessionFactory的方法</h4><ol>
<li>使用java类配置实现(SqlSessionFactoryBuilder)</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 配置数据库链接池</span></span><br><span class="line">PooledDataSource pooledDataSource = <span class="keyword">new</span> PooledDataSource();</span><br><span class="line">pooledDataSource.setDriver(<span class="string">"com.mysql.jdbc.Driver"</span>);</span><br><span class="line">pooledDataSource.setUrl(<span class="string">"jdbc:mysql://127.0.0.1:3306/mybatis"</span>);</span><br><span class="line">pooledDataSource.setUsername(<span class="string">"kys"</span>);</span><br><span class="line">pooledDataSource.setPassword(<span class="string">"password"</span>);</span><br><span class="line"><span class="comment">//构建数据库事物方式</span></span><br><span class="line">TransactionFactory transactionFactory = <span class="keyword">new</span> JdbcTransactionFactory();</span><br><span class="line"><span class="comment">//创建数据库运行环境</span></span><br><span class="line">Environment environment = <span class="keyword">new</span> Environment(<span class="string">"development"</span>, transactionFactory, pooledDataSource);</span><br><span class="line"><span class="comment">//构建configuration对象</span></span><br><span class="line">Configuration configuration = <span class="keyword">new</span> Configuration(environment);</span><br><span class="line"><span class="comment">//注册别名</span></span><br><span class="line">configuration.getTypeAliasRegistry().registerAlias(<span class="string">"xxx"</span>, xxx.class);</span><br><span class="line"><span class="comment">//添加映射文件等</span></span><br><span class="line">configuration.addMapper(xxx.class);</span><br><span class="line"><span class="comment">//等等。。。。</span></span><br><span class="line">SqlSessionFactory sessionFactory = <span class="keyword">new</span> SqlSessionFactoryBuilder().build(configuration);</span><br></pre></td></tr></table></figure>
<ol start="2">
<li>使用xml文档 输入流实现</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">String resource = <span class="string">"org/mybatis/builder/mybatis-config.xml"</span>;</span><br><span class="line">InputStream inputStream = Resources.getResourceAsStream(resource);</span><br><span class="line">SqlSessionFactoryBuilder builder = <span class="keyword">new</span> SqlSessionFactoryBuilder();</span><br><span class="line">SqlSessionFactory factory = builder.build(inputStream);</span><br></pre></td></tr></table></figure>
<h4 id="SqlSessionFactory-创建SqlSession实例"><a href="#SqlSessionFactory-创建SqlSession实例" class="headerlink" title="SqlSessionFactory 创建SqlSession实例"></a>SqlSessionFactory 创建SqlSession实例</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">SqlSession <span class="title">openSession</span><span class="params">()</span></span></span><br><span class="line"><span class="function">SqlSession <span class="title">openSession</span><span class="params">(<span class="keyword">boolean</span> autoCommit)</span>  <span class="comment">//是否自动提交</span></span></span><br><span class="line"><span class="function">SqlSession <span class="title">openSession</span><span class="params">(Connection connection)</span> </span></span><br><span class="line"><span class="function">SqlSession <span class="title">openSession</span><span class="params">(TransactionIsolationLevel level)</span>  <span class="comment">//事物隔离级别</span></span></span><br><span class="line"><span class="function">SqlSession <span class="title">openSession</span><span class="params">(ExecutorType execType,TransactionIsolationLevel level)</span></span></span><br><span class="line"><span class="function">SqlSession <span class="title">openSession</span><span class="params">(ExecutorType execType)</span>  <span class="comment">// 预处理问题</span></span></span><br><span class="line"><span class="function">SqlSession <span class="title">openSession</span><span class="params">(ExecutorType execType, <span class="keyword">boolean</span> autoCommit)</span></span></span><br><span class="line"><span class="function">SqlSession <span class="title">openSession</span><span class="params">(ExecutorType execType, Connection connection)</span></span></span><br><span class="line"><span class="function">Configuration <span class="title">getConfiguration</span><span class="params">()</span></span>;</span><br></pre></td></tr></table></figure>
<p><strong>相关参数配置：</strong></p>
<ol>
<li>事物隔离级别</li>
</ol>
<p>NONE(无),READ_UNCOMMITTED(读未提交),READ_COMMITTED(读已提交),REPEA TABLE_READ(可重复阅读),SERIALIZA BLE(序列化)</p>
<ol start="2">
<li>ExecutorType(执行方式)</li>
</ol>
<ul>
<li>ExecutorType.SIMPLE: 这个执行器类型不做特殊的事情。它为每个语句的执行创建一个新的预处理语句。</li>
<li>ExecutorType.REUSE: 这个执行器类型会复用预处理语句。</li>
<li>ExecutorType.BATCH: 这个执行器会批量执行所有更新语句,如果 - - SELECT 在它们中间执行还会标定它们是 必须的,来保证一个简单并易于理解的行为。</li>
</ul>
<h4 id="SqlSession-最核心的会话操作类"><a href="#SqlSession-最核心的会话操作类" class="headerlink" title="SqlSession 最核心的会话操作类"></a>SqlSession 最核心的会话操作类</h4><ol>
<li>语句执行方法</li>
</ol>
<p>这些方法被用来执行定义在 SQL 映射的 XML 文件中的 SELECT,INSERT,UPDA E T 和 DELETE 语句。它们都会自行解释,每一句都使用语句的 ID 属性和参数对象,参数可以 是原生类型(自动装箱或包装类) ,JavaBean,POJO 或 Map。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;T&gt; <span class="function">T <span class="title">selectOne</span><span class="params">(String statement, Object parameter)</span></span></span><br><span class="line"><span class="function">&lt;E&gt; List&lt;E&gt; <span class="title">selectList</span><span class="params">(String statement, Object parameter)</span></span></span><br><span class="line"><span class="function">&lt;K,V&gt; Map&lt;K,V&gt; <span class="title">selectMap</span><span class="params">(String statement, Object parameter, String mapKey)</span></span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">insert</span><span class="params">(String statement, Object parameter)</span></span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">update</span><span class="params">(String statement, Object parameter)</span></span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">delete</span><span class="params">(String statement, Object parameter)</span></span></span><br></pre></td></tr></table></figure>
<p><strong>注意</strong>：selectOne 和 selectList 的不同仅仅是 selectOne 必须返回一个对象。 如果多余一个, 或者 没有返回 (或返回了 null) 那么就会抛出异常。 , 如果你不知道需要多少对象, 使用 selectList。</p>
<p>最后,还有查询方法的三个高级版本,它们允许你限制返回行数的范围,或者提供自定 义结果控制逻辑,这通常用于大量的数据集合。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&lt;E&gt; <span class="function">List&lt;E&gt; <span class="title">selectList</span> <span class="params">(String statement, Object parameter, RowBounds rowBounds)</span></span></span><br><span class="line"><span class="function">&lt;K,V&gt; Map&lt;K,V&gt; <span class="title">selectMap</span><span class="params">(String statement, Object parameter, String mapKey, RowBounds rowbounds)</span></span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">select</span> <span class="params">(String statement, Object parameter, ResultHandler&lt;T&gt; handler)</span></span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">select</span> <span class="params">(String statement, Object parameter, RowBounds rowBounds, ResultHandler&lt;T&gt; handler)</span></span></span><br></pre></td></tr></table></figure>
<blockquote>
<p>RowBounds 参数会告诉 MyBatis 略过指定数量的记录,还有限制返回结果的数量。 </p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> offset = <span class="number">100</span>;  <span class="comment">//返回结果集的数量</span></span><br><span class="line"><span class="keyword">int</span> limit = <span class="number">25</span>;    <span class="comment">//忽略掉的行数</span></span><br><span class="line">RowBounds rowBounds = <span class="keyword">new</span> RowBounds(offset, limit);</span><br></pre></td></tr></table></figure>
<blockquote>
<p>ResultHandler 参数允许你按你喜欢的方式处理每一行。</p>
</blockquote>
<p>它的接口很简单。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> org.apache.ibatis.session;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">ResultHandler</span>&lt;<span class="title">T</span>&gt; </span>&#123;</span><br><span class="line">  <span class="function"><span class="keyword">void</span> <span class="title">handleResult</span><span class="params">(ResultContext&lt;? extends T&gt; context)</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>ResultContext 参数允许你访问结果对象本身、被创建的对象数目、以及返回值为 Boolean 的 stop 方法，你可以使用此 stop 方法来停止 MyBatis 加载更多的结果。<br>使用 ResultHandler 的时候需要注意以下两种限制：</p>
<ul>
<li>从被 ResultHandler 调用的方法返回的数据不会被缓存。</li>
<li>当使用结果映射集（resultMap）时，MyBatis 大多数情况下需要数行结果来构造外键对象。如果你正在使用 ResultHandler，你可以给出外键（association）或者集合（collection）尚未赋值的对象。</li>
</ul>
<ol start="2">
<li>批量立即更新方法(Flush Method)</li>
</ol>
<p>有一个方法可以刷新（执行）存储在JDBC驱动类中的批量更新语句。当你将ExecutorType.BATCH作为ExecutorType使用时可以采用此方法。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">List&lt;BatchResult&gt; <span class="title">flushStatements</span><span class="params">()</span></span></span><br></pre></td></tr></table></figure>
<ol start="3">
<li>事务控制方法</li>
</ol>
<p><strong>注意</strong>：如果你已经选择了自动提交或你正在使用外部事务管理器,这就没有任何效果了</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">commit</span><span class="params">()</span></span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">commit</span><span class="params">(<span class="keyword">boolean</span> force)</span></span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">rollback</span><span class="params">()</span></span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">rollback</span><span class="params">(<span class="keyword">boolean</span> force)</span></span></span><br></pre></td></tr></table></figure>
<ol start="4">
<li>清理Session级的缓存</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">List&lt;BatchResult&gt; <span class="keyword">void</span> <span class="title">clearCache</span><span class="params">()</span></span></span><br></pre></td></tr></table></figure>
<p>SqlSession 实例有一个本地缓存在执行 update,commit,rollback 和 close 时被清理。要 明确地关闭它(获取打算做更多的工作) ,你可以调用 clearCache()。</p>
<ol start="5">
<li>确保 SqlSession 被关闭</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">List&lt;BatchResult&gt; <span class="keyword">void</span> <span class="title">close</span><span class="params">()</span> </span></span><br><span class="line"><span class="function">`</span></span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">SqlSession session = sqlSessionFactory.openSession();</span><br><span class="line"><span class="keyword">try</span> &#123;</span><br><span class="line">    <span class="comment">// following 3 lines pseudocod for "doing some work"</span></span><br><span class="line">    session.insert(...);</span><br><span class="line">    session.update(...);</span><br><span class="line">    session.delete(...);</span><br><span class="line">    session.commit();</span><br><span class="line">&#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">    session.close();</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//java7以上使用try-with-resources语句</span></span><br><span class="line"><span class="keyword">try</span> (SqlSession session = sqlSessionFactory.openSession()) &#123;</span><br><span class="line">    <span class="comment">// following 3 lines pseudocode for "doing some work"</span></span><br><span class="line">    session.insert(...);</span><br><span class="line">    session.update(...);</span><br><span class="line">    session.delete(...);</span><br><span class="line">    session.commit();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ol start="6">
<li>高级应用 使用映射器 和常用注释操作</li>
</ol>
<p>type是mybatis的映射器类，是一个java接口，可以将接口类比成mybatis的map文件，包名称相当于xml中的namespace，而 select delete insert update 中的id属性 对应的 接口中的方法</p>
<p>最常用注解，用来进行动态的注入属性</p>
<table>
<thead>
<tr>
<th>注解</th>
<th>使用对象</th>
<th>相对应的XML</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>@CacheNamespace</td>
<td>类</td>
<td>&lt;cache&gt;</td>
<td>为给定的命名空间（比如类）配置缓存。属性有：implemetation,eviction,flushInterval,size,readWrite,blocking和properties。</td>
</tr>
<tr>
<td>@Property</td>
<td>N/A</td>
<td>&lt;property&gt;</td>
<td>指定参数值或占位值（placeholder）（能被mybatis-config.xml内的配置属性覆盖）。属性有：name,value。（仅在MyBatis3.4.2以上版本生效）</td>
</tr>
<tr>
<td>@CacheNamespaceRef</td>
<td>类</td>
<td>&lt;cacheRef&gt;</td>
<td>参照另外一个命名空间的缓存来使用。属性有：value,name。如果你使用了这个注解，你应设置value或者name属性的其中一个。value属性用于指定Java类型而指定命名空间（命名空间名就是指定的Java类型的全限定名），name属性（这个属性仅在MyBatis3.4.2以上版本生效）直接指定了命名空间的名字。</td>
</tr>
<tr>
<td>@ConstructorArgs</td>
<td>方法</td>
<td>&lt;constructor&gt;</td>
<td>收集一组结果传递给一个结果对象的构造方法。属性有：value，它是形式参数数组。</td>
</tr>
<tr>
<td>@Arg</td>
<td>N/A</td>
<td>&lt;arg&gt;</td>
<td>单参数构造方法，是ConstructorArgs集合的一部分。属性有：id,column,javaType,jdbcType,typeHandler,select和resultMap。id属性是布尔值，来标识用于比较的属性，和&lt;idArg&gt;XML元素相似。</td>
</tr>
<tr>
<td>&lt;idArg&gt;</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>@TypeDiscriminator</td>
<td>方法</td>
<td>&lt;discriminator&gt;</td>
<td>一组实例值被用来决定结果映射的表现。属性有：column,javaType,jdbcType,typeHandler和cases。cases属性是实例数组。</td>
</tr>
<tr>
<td>@Case</td>
<td>N/A</td>
<td>&lt;case&gt;</td>
<td>单独实例的值和它对应的映射。属性有：value,type,results。results属性是结果数组，因此这个注解和实际的ResultMap很相似，由下面的Results注解指定。</td>
</tr>
<tr>
<td>@Results</td>
<td>方法</td>
<td>&lt;resultMap&gt;</td>
<td>结果映射的列表，包含了一个特别结果列如何被映射到属性或字段的详情。属性有：value,id。value属性是Result注解的数组。这个id的属性是结果映射的名称。</td>
</tr>
<tr>
<td>@Result</td>
<td>N/A</td>
<td>&lt;result&gt;</td>
<td>在列和属性或字段之间的单独结果映射。属性有：id,column,javaType,jdbcType,typeHandler,one,many。id属性是一个布尔值，来标识应该被用于比较（和在XML映射中的&lt;id&gt;相似）的属性。one属性是单独的联系，和&lt;association&gt;相似，而many属性是对集合而言的，和&lt;collection&gt;相似。它们这样命名是为了避免名称冲突。</td>
</tr>
<tr>
<td>&lt;id&gt;</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>@One</td>
<td>N/A</td>
<td>&lt;association&gt;</td>
<td>复杂类型的单独属性值映射。属性有：select，已映射语句（也就是映射器方法）的全限定名，它可以加载合适类型的实例。fetchType会覆盖全局的配置参数lazyLoadingEnabled。注意联合映射在注解API中是不支持的。这是因为Java注解的限制,不允许循环引用。</td>
</tr>
<tr>
<td>@Many</td>
<td>N/A</td>
<td>&lt;collection&gt;</td>
<td>映射到复杂类型的集合属性。属性有：select，已映射语句（也就是映射器方法）的全限定名，它可以加载合适类型的实例的集合，fetchType会覆盖全局的配置参数lazyLoadingEnabled。注意联合映射在注解API中是不支持的。这是因为Java注解的限制，不允许循环引用</td>
</tr>
<tr>
<td>@MapKey</td>
<td>方法</td>
<td></td>
<td>这是一个用在返回值为Map的方法上的注解。它能够将存放对象的List转化为key值为对象的某一属性的Map。属性有：value，填入的是对象的属性名，作为Map的key值。</td>
</tr>
<tr>
<td>@Options</td>
<td>方法</td>
<td>映射语句的属性</td>
<td>这个注解提供访问大范围的交换和配置选项的入口，它们通常在映射语句上作为属性出现。Options注解提供了通俗易懂的方式来访问它们，而不是让每条语句注解变复杂。属性有：useCache=true,flushCache=FlushCachePolicy.DEFAULT,resultSetType=FORWARD_ONLY,statementType=PREPARED,fetchSize=-1,timeout=-1,useGeneratedKeys=false,keyProperty=”id”,keyColumn=””,resultSets=””。值得一提的是，Java注解无法指定null值。因此，一旦你使用了Options注解，你的语句就会被上述属性的默认值所影响。要注意避免默认值带来的预期以外的行为。</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>注意：keyColumn属性只在某些数据库中有效（如Oracle、PostgreSQL等）。请在插入语句一节查看更多关于keyColumn和keyProperty两者的有效值详情。</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>@Insert</td>
<td>方法</td>
<td>&lt;insert&gt;</td>
<td>这四个注解分别代表将会被执行的SQL语句。它们用字符串数组（或单个字符串）作为参数。如果传递的是字符串数组，字符串之间先会被填充一个空格再连接成单个完整的字符串。这有效避免了以Java代码构建SQL语句时的“丢失空格”的问题。然而，你也可以提前手动连接好字符串。属性有：value，填入的值是用来组成单个SQL语句的字符串数组。</td>
</tr>
<tr>
<td>@Update</td>
<td>&lt;update&gt;</td>
<td></td>
<td></td>
</tr>
<tr>
<td>@Delete</td>
<td>&lt;delete&gt;</td>
<td></td>
<td></td>
</tr>
<tr>
<td>@Select</td>
<td>&lt;select&gt;</td>
<td></td>
<td></td>
</tr>
<tr>
<td>@InsertProvider</td>
<td>方法</td>
<td>&lt;insert&gt;</td>
<td>允许构建动态SQL。这些备选的SQL注解允许你指定类名和返回在运行时执行的SQL语句的方法。（自从MyBatis3.4.6开始，你可以用CharSequence代替String来返回类型返回值了。）当执行映射语句的时候，MyBatis会实例化类并执行方法，类和方法就是填入了注解的值。你可以把已经传递给映射方法了的对象作为参数，”Mapperinterfacetype”和”Mappermethod”会经过ProviderContext（仅在MyBatis3.4.5及以上支持）作为参数值。（MyBatis3.4及以上的版本，支持多参数传入）属性有：type,method。type属性需填入类。method需填入该类定义了的方法名。注意接下来的小节将会讨论类，能帮助你更轻松地构建动态SQL。</td>
</tr>
<tr>
<td>@UpdateProvider</td>
<td>&lt;update&gt;</td>
<td></td>
<td></td>
</tr>
<tr>
<td>@DeleteProvider</td>
<td>&lt;delete&gt;</td>
<td></td>
<td></td>
</tr>
<tr>
<td>@SelectProvider</td>
<td>&lt;select&gt;</td>
<td></td>
<td></td>
</tr>
<tr>
<td>@Param</td>
<td>参数</td>
<td>N/A</td>
<td>如果你的映射方法的形参有多个，这个注解使用在映射方法的参数上就能为它们取自定义名字。若不给出自定义名字，多参数（不包括RowBounds参数）则先以”param”作前缀，再加上它们的参数位置作为参数别名。例如#{param1},#{param2}，这个是默认值。如果注解是@Param(“person”)，那么参数就会被命名为#{person}。</td>
</tr>
<tr>
<td>@SelectKey</td>
<td>方法</td>
<td>&lt;selectKey&gt;</td>
<td>这个注解的功能与&lt;selectKey&gt;标签完全一致，用在已经被@Insert或@InsertProvider或@Update或@UpdateProvider注解了的方法上。若在未被上述四个注解的方法上作@SelectKey注解则视为无效。如果你指定了@SelectKey注解，那么MyBatis就会忽略掉由@Options注解所设置的生成主键或设置（configuration）属性。属性有：statement填入将会被执行的SQL字符串数组，keyProperty填入将会被更新的参数对象的属性的值，before填入true或false以指明SQL语句应被在插入语句的之前还是之后执行。resultType填入keyProperty的Java类型和用Statement、PreparedStatement和CallableStatement中的STATEMENT、PREPARED或CALLABLE中任一值填入statementType。默认值是PREPARED。</td>
</tr>
<tr>
<td>@ResultMap</td>
<td>方法</td>
<td>N/A</td>
<td>这个注解给@Select或者@SelectProvider提供在XML映射中的&lt;resultMap&gt;的id。这使得注解的select可以复用那些定义在XML中的ResultMap。如果同一select注解中还存在@Results或者@ConstructorArgs，那么这两个注解将被此注解覆盖。</td>
</tr>
<tr>
<td>@ResultType</td>
<td>方法</td>
<td>N/A</td>
<td>此注解在使用了结果处理器的情况下使用。在这种情况下，返回类型为void，所以Mybatis必须有一种方式决定对象的类型，用于构造每行数据。如果有XML的结果映射，请使用@ResultMap注解。如果结果类型在XML的&lt;select&gt;节点中指定了，就不需要其他的注解了。其他情况下则使用此注解。比如，如果@Select注解在一个将使用结果处理器的方法上，那么返回类型必须是void并且这个注解（或者@ResultMap）必选。这个注解仅在方法返回类型是void的情况下生效。</td>
</tr>
<tr>
<td>@Flush</td>
<td>方法</td>
<td>N/A</td>
<td>如果使用了这个注解，定义在Mapper接口中的方法能够调用SqlSession#flushStatements()方法。（Mybatis3.3及以上）</td>
</tr>
</tbody>
</table>

          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2018/10/09/深入理解mybatis（七）mybatis和spring结合/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="kyssion">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="kyssion-blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2018/10/09/深入理解mybatis（七）mybatis和spring结合/" itemprop="url">未命名</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-10-09T15:22:37+08:00">
                2018-10-09
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h2 id="深入理解mybatis（七）mybatis和spring结合"><a href="#深入理解mybatis（七）mybatis和spring结合" class="headerlink" title="深入理解mybatis（七）mybatis和spring结合"></a>深入理解mybatis（七）mybatis和spring结合</h2><p>实现mybatis和spring的整合的时候注意spring在和mybatis整合的时候需要使用额外的依赖配置</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.mybatis<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mybatis-spring<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">version</span>&gt;</span>x.x.x<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h3 id="SqlSessionFactoryBean"><a href="#SqlSessionFactoryBean" class="headerlink" title="SqlSessionFactoryBean"></a>SqlSessionFactoryBean</h3><p>在基本的 MyBatis 中,session 工厂可以使用 SqlSessionFactoryBuilder 来创建。而在 MyBatis-Spring 中,则使用 SqlSessionFactoryBean 来替代。</p>
<p>要注意这个配置文件不需要是一个完整的 MyBatis 配置。确切地说,任意环境,数据源 和 MyBatis 的事务管理器都会被忽略。SqlSessionFactoryBean 会创建它自己的,使用这些 值定制 MyBatis 的 Environment 时是需要的。</p>
<p>如果MyBatis映射器XML文件在和映射器类相同的路径下不存在,那么另外一个需要 配置文件的原因就是它了。使用这个配置,有两种选择。第一是手动在 MyBatis 的 XML 配 置文件中使用<mappers>部分来指定类路径。第二是使用工厂bean的mapperLocations属性。</mappers></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"sqlSessionFactory"</span> <span class="attr">class</span>=<span class="string">"org.mybatis.spring.SqlSessionFactoryBean"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"dataSource"</span> <span class="attr">ref</span>=<span class="string">"dataSource"</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>以上配置文件相当于以下java语句</p>
<blockquote>
<p>要注意 SqlSessionFactoryBean 实现了 Spring 的 FactoryBean 接口(请参考 Spring 文 档的 3.8 章节)这就说明了由 Spring 最终创建的 bean 不是 SqlSessionFactoryBean 本身, 。 而是工厂类的 getObject()返回的方法的结果。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">SqlSessionFactoryBean factoryBean = <span class="keyword">new</span> SqlSessionFactoryBean();</span><br><span class="line">SqlSessionFactory sessionFactory = factoryBean.getObject();</span><br></pre></td></tr></table></figure>
<h3 id="添加事物管理"><a href="#添加事物管理" class="headerlink" title="添加事物管理"></a>添加事物管理</h3><p>很简单只要将声明并且传入SqlSessionFactoryBean中的datasource添加上相关事务性操作的就好了 和 一般的spring事务配置相同</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"transactionManager"</span> <span class="attr">class</span>=<span class="string">"org.springframework.jdbc.datasource.DataSourceTransactionManager"</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"dataSource"</span> <span class="attr">ref</span>=<span class="string">"dataSource"</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">tx:annotation-driven</span> <span class="attr">transaction-manager</span>=<span class="string">"transactionManager"</span>/&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span>(<span class="string">"moneyService"</span>)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MoneyService</span> </span>&#123;</span><br><span class="line">	<span class="meta">@Resource</span>(name=<span class="string">"userMoney"</span>)</span><br><span class="line">	<span class="keyword">public</span> UserMoney userMoney;</span><br><span class="line">	<span class="meta">@Transactional</span>(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED)</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">okStart</span><span class="params">(People from,People to)</span> </span>&#123;</span><br><span class="line">		userMoney.addMoney(from.getMoney(), from);</span><br><span class="line">		userMoney.deductMoney(to.getMoney(), to);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="使用-SqlSessionTemplate-代替sqlSession"><a href="#使用-SqlSessionTemplate-代替sqlSession" class="headerlink" title="使用 SqlSessionTemplate 代替sqlSession"></a>使用 SqlSessionTemplate 代替sqlSession</h3><p>SqlSessionTemplate 对象可以使用 SqlSessionFactory 作为构造方法的参数来代替Sqlsession。应为它实现了Sqlsession接口`</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"sqlSession"</span> <span class="attr">class</span>=<span class="string">"org.mybatis.spring.SqlSessionTemplate"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">index</span>=<span class="string">"0"</span> <span class="attr">ref</span>=<span class="string">"sqlSessionFactory"</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>将SqlSession配置到bean中</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"userDao"</span> <span class="attr">class</span>=<span class="string">"org.mybatis.spring.sample.dao.UserDaoImpl"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"sqlSession"</span> <span class="attr">ref</span>=<span class="string">"sqlSession"</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>java代码使用注入进来的SqlSession</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UserDaoImpl</span> <span class="keyword">implements</span> <span class="title">UserDao</span> </span>&#123;</span><br><span class="line"> </span><br><span class="line">  <span class="keyword">private</span> SqlSession sqlSession;</span><br><span class="line"> </span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setSqlSession</span><span class="params">(SqlSession sqlSession)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">this</span>.sqlSession = sqlSession;</span><br><span class="line">  &#125;</span><br><span class="line"> </span><br><span class="line">  <span class="function"><span class="keyword">public</span> User <span class="title">getUser</span><span class="params">(String userId)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> (User) sqlSession.selectOne(<span class="string">"org.mybatis.spring.sample.mapper.UserMapper.getUser"</span>, userId);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>SqlSessionTemplate 有一个使用 ExecutorType 作为参数的构造方法。这允许你用来 创建对象,比如,一个批量 SqlSession,但是使用了下列 Spring 配置的 XML 文件:</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"sqlSession"</span> <span class="attr">class</span>=<span class="string">"org.mybatis.spring.SqlSessionTemplate"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">index</span>=<span class="string">"0"</span> <span class="attr">ref</span>=<span class="string">"sqlSessionFactory"</span> /&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">index</span>=<span class="string">"1"</span> <span class="attr">value</span>=<span class="string">"BATCH"</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>现在你所有的语句可以批量操作了,下面的语句就可以在 DAO 中使用了。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">insertUsers</span><span class="params">(User[] users)</span> </span>&#123;</span><br><span class="line">   <span class="keyword">for</span> (User user : users) &#123;</span><br><span class="line">     sqlSession.insert(<span class="string">"org.mybatis.spring.sample.mapper.UserMapper.insertUser"</span>, user);</span><br><span class="line">   &#125;</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure>
<h3 id="MapperFactoryBean"><a href="#MapperFactoryBean" class="headerlink" title="MapperFactoryBean"></a>MapperFactoryBean</h3><p>为了代替手工使用 SqlSessionDaoSupport 或 SqlSessionTemplate 编写数据访问对象 (DAO)的代码,MyBatis-Spring 提供了一个动态代理的实现:MapperFactoryBean。这个类 可以让你直接注入数据映射器接口到你的 service 层 bean 中。当使用映射器时,你仅仅如调 用你的 DAO 一样调用它们就可以了,但是你不需要编写任何 DAO 实现的代码,因为 MyBatis-Spring 将会为你创建代理。</p>
<p>配置方法</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"userMapper"</span> <span class="attr">class</span>=<span class="string">"org.mybatis.spring.mapper.MapperFactoryBean"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"mapperInterface"</span> <span class="attr">value</span>=<span class="string">"org.mybatis.spring.sample.mapper.UserMapper"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"sqlSessionFactory"</span> <span class="attr">ref</span>=<span class="string">"sqlSessionFactory"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"sqlSessionTemplate"</span> <span class="attr">ref</span>=<span class="string">"sqlSessionTemplate"</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>通过配置得到的bean等价于使用sqlSession.getMapper(xxx.class);方法的返回结果</p>
<blockquote>
<p>注意：传入的接口信息，应该可以在传入的SqlSessionFactory配置的mapper映射文件中有相应的namespace</p>
</blockquote>
<blockquote>
<p>注意,当 MapperFactoryBean 需要 SqlSessionFactory 或 SqlSessionTemplate 时。 这些可以通过各自的 SqlSessionFactory 或 SqlSessionTemplate 属性来设置, 或者可以由 Spring 来自动装配。如果两个属性都设置了,那么 SqlSessionFactory 就会被忽略,因为 SqlSessionTemplate 是需要有一个 session 工厂的设置; 那个工厂会由 MapperFactoryBean. 来使用。</p>
</blockquote>
<p>可以直接在 business/service 对象中以和注入任意 Spring bean 的相同方式直接注入映 射器:</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"fooService"</span> <span class="attr">class</span>=<span class="string">"org.mybatis.spring.sample.mapper.FooServiceImpl"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"userMapper"</span> <span class="attr">ref</span>=<span class="string">"userMapper"</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FooServiceImpl</span> <span class="keyword">implements</span> <span class="title">FooService</span> </span>&#123;</span><br><span class="line"> </span><br><span class="line">  <span class="keyword">private</span> UserMapper userMapper;</span><br><span class="line"> </span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setUserMapper</span><span class="params">(UserMapper userMapper)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">this</span>.userMapper = userMapper;</span><br><span class="line">  &#125;</span><br><span class="line"> </span><br><span class="line">  <span class="function"><span class="keyword">public</span> User <span class="title">doSomeBusinessStuff</span><span class="params">(String userId)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">this</span>.userMapper.getUser(userId);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="使用MapperScannerConfigurer简化配置"><a href="#使用MapperScannerConfigurer简化配置" class="headerlink" title="使用MapperScannerConfigurer简化配置"></a>使用MapperScannerConfigurer简化配置</h3><p>使用mapperFactoryBean的时候感觉每一个映射接口都要进行相关的配置，所以我们需要为一个可以自动进行所有配置的整合配置方法</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">class</span>=<span class="string">"org.mybatis.spring.mapper.MapperScannerConfigurer"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"basePackage"</span> <span class="attr">value</span>=<span class="string">"org.dao"</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--&lt;property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"&gt;&lt;/property&gt; --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"sqlSessionTemplateBeanName"</span> <span class="attr">value</span>=<span class="string">"sqlSession"</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 限定型操作，指定要进行寻找的注解名称或者接口名称 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"annotationClass"</span> <span class="attr">value</span>=<span class="string">"org.springframework.stereotype."</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"markerInterface"</span> <span class="attr">value</span>=<span class="string">"org.dao.xxxx"</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>这个注解可以替代mapperFactoryBean，而且，只要指定包名称，框架将会自动按照spring注解的命名规则将相关接口注入到spring的命名空间中（可以使用spring的自动扫描注解，指定映射名称）</p>
<blockquote>
<p>2018年8月补充 通过阅读源代码发现 @Mapper这个注解在spring-mybatis和mybatis 本身中更本不起道任何作用，只有在spring boot中有过使用（不过大多数的都是直接使用@MapperScan）</p>
</blockquote>
<h3 id="一个实例"><a href="#一个实例" class="headerlink" title="一个实例"></a>一个实例</h3><blockquote>
<p>mybatis的相关配置文件</p>
</blockquote>
<ol>
<li>mybatis-config.xml</li>
</ol>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span><br><span class="line"><span class="meta">&lt;!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">settings</span>&gt;</span></span><br><span class="line">		<span class="tag">&lt;<span class="name">setting</span> <span class="attr">name</span>=<span class="string">"logImpl"</span> <span class="attr">value</span>=<span class="string">"STDOUT_LOGGING"</span>/&gt;</span></span><br><span class="line">		<span class="tag">&lt;<span class="name">setting</span> <span class="attr">name</span>=<span class="string">"mapUnderscoreToCamelCase"</span> <span class="attr">value</span>=<span class="string">"true"</span>/&gt;</span></span><br><span class="line">	<span class="tag">&lt;/<span class="name">settings</span>&gt;</span></span><br><span class="line">	<span class="comment">&lt;!-- 和sping框架进行结合的时候不需要使用enviroment标签spring框架会自动的设置好 --&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">mappers</span>&gt;</span></span><br><span class="line">		<span class="tag">&lt;<span class="name">mapper</span> <span class="attr">resource</span>=<span class="string">"mymapper.xml"</span>/&gt;</span></span><br><span class="line">	<span class="tag">&lt;/<span class="name">mappers</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br></pre></td></tr></table></figure>
<ol start="2">
<li>mymapper.xml</li>
</ol>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span><br><span class="line"><span class="meta">&lt;!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">mapper</span> <span class="attr">namespace</span>=<span class="string">"org.dao.UserMoney"</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">resultMap</span> <span class="attr">type</span>=<span class="string">"org.user.People"</span> <span class="attr">id</span>=<span class="string">"people"</span>&gt;</span></span><br><span class="line">		<span class="tag">&lt;<span class="name">id</span> <span class="attr">column</span>=<span class="string">"name"</span> <span class="attr">jdbcType</span>=<span class="string">"VARBINARY"</span> <span class="attr">javaType</span>=<span class="string">"string"</span>/&gt;</span></span><br><span class="line">		<span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">"money"</span> <span class="attr">jdbcType</span>=<span class="string">"INTEGER"</span> <span class="attr">javaType</span>=<span class="string">"int"</span>/&gt;</span></span><br><span class="line">	<span class="tag">&lt;/<span class="name">resultMap</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">update</span> <span class="attr">id</span>=<span class="string">"addMoney"</span> <span class="attr">parameterType</span>=<span class="string">"org.user.People"</span> <span class="attr">statementType</span>=<span class="string">"PREPARED"</span>&gt;</span></span><br><span class="line">		update user set money=#&#123;money&#125; where name= #&#123;people.name&#125;</span><br><span class="line">	<span class="tag">&lt;/<span class="name">update</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">update</span> <span class="attr">id</span>=<span class="string">"deductMoney"</span> <span class="attr">parameterType</span>=<span class="string">"org.user.People"</span> <span class="attr">statementType</span>=<span class="string">"PREPARED"</span>&gt;</span></span><br><span class="line">		update user set money=#&#123;money&#125; where name= #&#123;people.name&#125;</span><br><span class="line">	<span class="tag">&lt;/<span class="name">update</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">"showMoney"</span> <span class="attr">resultMap</span>=<span class="string">"people"</span>&gt;</span></span><br><span class="line">		select * from user;</span><br><span class="line">	<span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">mapper</span>&gt;</span></span><br></pre></td></tr></table></figure>
<blockquote>
<p>bean相关配置文件和数据库连接池相关配置</p>
</blockquote>
<ol>
<li>datasource.properties</li>
</ol>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">url=jdbc:mysql://localhost:3306/demo</span><br><span class="line">driverClassName=com.mysql.jdbc.Driver</span><br><span class="line">username=root</span><br><span class="line">password=14159265jkl</span><br><span class="line">filters=stat</span><br><span class="line">maxActive=20</span><br><span class="line">initialSize=1</span><br><span class="line">maxWait=60000</span><br><span class="line">minIdle=10</span><br><span class="line">maxIdle=15</span><br><span class="line">timeBetweenEvictionRunsMillis=60000</span><br><span class="line">minEvictableIdleTimeMillis=300000</span><br><span class="line">validationQuery=SELECT &apos;x&apos;</span><br><span class="line">testWhileIdle=true</span><br><span class="line">testOnBorrow=false</span><br><span class="line">testOnReturn=false</span><br><span class="line">maxOpenPreparedStatements=20</span><br><span class="line">removeAbandoned=true</span><br><span class="line">removeAbandonedTimeout=1800</span><br><span class="line">logAbandoned=true</span><br></pre></td></tr></table></figure>
<ol start="2">
<li>bean.xml</li>
</ol>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br></pre></td><td class="code"><pre><span class="line">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span><br><span class="line"><span class="tag">&lt;<span class="name">beans</span> <span class="attr">xmlns</span>=<span class="string">"http://www.springframework.org/schema/beans"</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:aop</span>=<span class="string">"http://www.springframework.org/schema/aop"</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:context</span>=<span class="string">"http://www.springframework.org/schema/context"</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:tx</span>=<span class="string">"http://www.springframework.org/schema/tx"</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd</span></span></span><br><span class="line"><span class="tag"><span class="string">		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd</span></span></span><br><span class="line"><span class="tag"><span class="string">		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd</span></span></span><br><span class="line"><span class="tag"><span class="string">		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">"org.dao"</span>&gt;</span><span class="tag">&lt;/<span class="name">context:component-scan</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">"org.user"</span>&gt;</span><span class="tag">&lt;/<span class="name">context:component-scan</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">"org.Service"</span>&gt;</span><span class="tag">&lt;/<span class="name">context:component-scan</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 启用配置文件设置方法 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"propertyConfigurer"</span> <span class="attr">class</span>=<span class="string">"org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"locations"</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">list</span> <span class="attr">value-type</span>=<span class="string">"java.lang.String"</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">value</span>&gt;</span>classpath:datasource.properties<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">list</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 配置数据源 使用阿里巴巴数据库连接池 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span> = <span class="string">"dataSource"</span> <span class="attr">class</span> = <span class="string">"com.alibaba.druid.pool.DruidDataSource"</span> <span class="attr">destroy-method</span> = <span class="string">"close"</span> &gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 数据库基本信息配置 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"url"</span> <span class="attr">value</span> = <span class="string">"$&#123;url&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"username"</span> <span class="attr">value</span> = <span class="string">"$&#123;username&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"password"</span> <span class="attr">value</span> = <span class="string">"$&#123;password&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"driverClassName"</span> <span class="attr">value</span> = <span class="string">"$&#123;driverClassName&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"filters"</span> <span class="attr">value</span> = <span class="string">"$&#123;filters&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 最大并发连接数 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"maxActive"</span> <span class="attr">value</span> = <span class="string">"$&#123;maxActive&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 初始化连接数量 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"initialSize"</span> <span class="attr">value</span> = <span class="string">"$&#123;initialSize&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 配置获取连接等待超时的时间 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"maxWait"</span> <span class="attr">value</span> = <span class="string">"$&#123;maxWait&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 最小空闲连接数 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"minIdle"</span> <span class="attr">value</span> = <span class="string">"$&#123;minIdle&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"timeBetweenEvictionRunsMillis"</span> <span class="attr">value</span> =<span class="string">"$&#123;timeBetweenEvictionRunsMillis&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 配置一个连接在池中最小生存的时间，单位是毫秒 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"minEvictableIdleTimeMillis"</span> <span class="attr">value</span> =<span class="string">"$&#123;minEvictableIdleTimeMillis&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"validationQuery"</span> <span class="attr">value</span> = <span class="string">"$&#123;validationQuery&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"testWhileIdle"</span> <span class="attr">value</span> = <span class="string">"$&#123;testWhileIdle&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"testOnBorrow"</span> <span class="attr">value</span> = <span class="string">"$&#123;testOnBorrow&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"testOnReturn"</span> <span class="attr">value</span> = <span class="string">"$&#123;testOnReturn&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"maxOpenPreparedStatements"</span> <span class="attr">value</span> =<span class="string">"$&#123;maxOpenPreparedStatements&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 打开 removeAbandoned 功能 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"removeAbandoned"</span> <span class="attr">value</span> = <span class="string">"$&#123;removeAbandoned&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 1800 秒，也就是 30 分钟 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"removeAbandonedTimeout"</span> <span class="attr">value</span> =<span class="string">"$&#123;removeAbandonedTimeout&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 关闭 abanded 连接时输出错误日志 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"logAbandoned"</span> <span class="attr">value</span> = <span class="string">"$&#123;logAbandoned&#125;"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 配置spring和mybatis 整合部分 --&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 生成 sqlsessionFactory --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"sqlSessionFactory"</span> <span class="attr">class</span>=<span class="string">"org.mybatis.spring.SqlSessionFactoryBean"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"dataSource"</span> <span class="attr">ref</span>=<span class="string">"dataSource"</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"configLocation"</span> <span class="attr">value</span>=<span class="string">"classpath:mybatis-config.xml"</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--</span></span><br><span class="line"><span class="comment">        &lt;property name="mapperLocations" value="classpath:xxx/*xml"&gt;&lt;/property&gt;</span></span><br><span class="line"><span class="comment">         --&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 指定某个路径下所有的配置文件使用通配符号 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 开起spring 事务 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"transactionManager"</span> <span class="attr">class</span>=<span class="string">"org.springframework.jdbc.datasource.DataSourceTransactionManager"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"dataSource"</span> <span class="attr">ref</span>=<span class="string">"dataSource"</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">tx:annotation-driven</span> <span class="attr">transaction-manager</span>=<span class="string">"transactionManager"</span>/&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 使用SqlSessionTemplate  --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"sqlSession"</span> <span class="attr">class</span>=<span class="string">"org.mybatis.spring.SqlSessionTemplate"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">index</span>=<span class="string">"0"</span> <span class="attr">ref</span>=<span class="string">"sqlSessionFactory"</span>&gt;</span><span class="tag">&lt;/<span class="name">constructor-arg</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 使用配置类型  ExecutorType  --&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- &lt;constructor-arg index="1" value="BATCH"&gt;&lt;/constructor-arg&gt;--&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"userMoney"</span> <span class="attr">class</span>=<span class="string">"org.mybatis.spring.mapper.MapperFactoryBean"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"mapperInterface"</span> <span class="attr">value</span>=<span class="string">"org.dao.UserMoney"</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"sqlSessionTemplate"</span> <span class="attr">ref</span>=<span class="string">"sqlSession"</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">beans</span>&gt;</span></span><br></pre></td></tr></table></figure>
<blockquote>
<p>使用mapperconfig进行配置</p>
</blockquote>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br></pre></td><td class="code"><pre><span class="line">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span><br><span class="line"><span class="tag">&lt;<span class="name">beans</span> <span class="attr">xmlns</span>=<span class="string">"http://www.springframework.org/schema/beans"</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:aop</span>=<span class="string">"http://www.springframework.org/schema/aop"</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:context</span>=<span class="string">"http://www.springframework.org/schema/context"</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:tx</span>=<span class="string">"http://www.springframework.org/schema/tx"</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd</span></span></span><br><span class="line"><span class="tag"><span class="string">		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd</span></span></span><br><span class="line"><span class="tag"><span class="string">		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd</span></span></span><br><span class="line"><span class="tag"><span class="string">		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">"org.dao"</span>&gt;</span><span class="tag">&lt;/<span class="name">context:component-scan</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">"org.user"</span>&gt;</span><span class="tag">&lt;/<span class="name">context:component-scan</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">"org.Service"</span>&gt;</span><span class="tag">&lt;/<span class="name">context:component-scan</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 启用配置文件设置方法 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"propertyConfigurer"</span> <span class="attr">class</span>=<span class="string">"org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"locations"</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">list</span> <span class="attr">value-type</span>=<span class="string">"java.lang.String"</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">value</span>&gt;</span>classpath:datasource.properties<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">list</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 配置数据源 使用阿里巴巴数据库连接池 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span> = <span class="string">"dataSource"</span> <span class="attr">class</span> = <span class="string">"com.alibaba.druid.pool.DruidDataSource"</span> <span class="attr">destroy-method</span> = <span class="string">"close"</span> &gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 数据库基本信息配置 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"url"</span> <span class="attr">value</span> = <span class="string">"$&#123;url&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"username"</span> <span class="attr">value</span> = <span class="string">"$&#123;username&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"password"</span> <span class="attr">value</span> = <span class="string">"$&#123;password&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"driverClassName"</span> <span class="attr">value</span> = <span class="string">"$&#123;driverClassName&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"filters"</span> <span class="attr">value</span> = <span class="string">"$&#123;filters&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 最大并发连接数 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"maxActive"</span> <span class="attr">value</span> = <span class="string">"$&#123;maxActive&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 初始化连接数量 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"initialSize"</span> <span class="attr">value</span> = <span class="string">"$&#123;initialSize&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 配置获取连接等待超时的时间 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"maxWait"</span> <span class="attr">value</span> = <span class="string">"$&#123;maxWait&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 最小空闲连接数 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"minIdle"</span> <span class="attr">value</span> = <span class="string">"$&#123;minIdle&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"timeBetweenEvictionRunsMillis"</span> <span class="attr">value</span> =<span class="string">"$&#123;timeBetweenEvictionRunsMillis&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 配置一个连接在池中最小生存的时间，单位是毫秒 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"minEvictableIdleTimeMillis"</span> <span class="attr">value</span> =<span class="string">"$&#123;minEvictableIdleTimeMillis&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"validationQuery"</span> <span class="attr">value</span> = <span class="string">"$&#123;validationQuery&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"testWhileIdle"</span> <span class="attr">value</span> = <span class="string">"$&#123;testWhileIdle&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"testOnBorrow"</span> <span class="attr">value</span> = <span class="string">"$&#123;testOnBorrow&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"testOnReturn"</span> <span class="attr">value</span> = <span class="string">"$&#123;testOnReturn&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"maxOpenPreparedStatements"</span> <span class="attr">value</span> =<span class="string">"$&#123;maxOpenPreparedStatements&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 打开 removeAbandoned 功能 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"removeAbandoned"</span> <span class="attr">value</span> = <span class="string">"$&#123;removeAbandoned&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 1800 秒，也就是 30 分钟 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"removeAbandonedTimeout"</span> <span class="attr">value</span> =<span class="string">"$&#123;removeAbandonedTimeout&#125;"</span> /&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 关闭 abanded 连接时输出错误日志 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">"logAbandoned"</span> <span class="attr">value</span> = <span class="string">"$&#123;logAbandoned&#125;"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 配置spring和mybatis 整合部分 --&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 生成 sqlsessionFactory --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"sqlSessionFactory"</span> <span class="attr">class</span>=<span class="string">"org.mybatis.spring.SqlSessionFactoryBean"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"dataSource"</span> <span class="attr">ref</span>=<span class="string">"dataSource"</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"configLocation"</span> <span class="attr">value</span>=<span class="string">"classpath:mybatis-config.xml"</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--</span></span><br><span class="line"><span class="comment">        &lt;property name="mapperLocations" value="classpath:xxx/*xml"&gt;&lt;/property&gt;</span></span><br><span class="line"><span class="comment">         --&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 指定某个路径下所有的配置文件使用通配符号 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 开起spring 事务 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"transactionManager"</span> <span class="attr">class</span>=<span class="string">"org.springframework.jdbc.datasource.DataSourceTransactionManager"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"dataSource"</span> <span class="attr">ref</span>=<span class="string">"dataSource"</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">tx:annotation-driven</span> <span class="attr">transaction-manager</span>=<span class="string">"transactionManager"</span>/&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 使用SqlSessionTemplate  --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"sqlSession"</span> <span class="attr">class</span>=<span class="string">"org.mybatis.spring.SqlSessionTemplate"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">index</span>=<span class="string">"0"</span> <span class="attr">ref</span>=<span class="string">"sqlSessionFactory"</span>&gt;</span><span class="tag">&lt;/<span class="name">constructor-arg</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 使用配置类型  ExecutorType  --&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- &lt;constructor-arg index="1" value="BATCH"&gt;&lt;/constructor-arg&gt;--&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- </span></span><br><span class="line"><span class="comment">    &lt;bean id="userMoney" class="org.mybatis.spring.mapper.MapperFactoryBean"&gt;</span></span><br><span class="line"><span class="comment">            &lt;property name="mapperInterface" value="org.dao.UserMoney"&gt;&lt;/property&gt;</span></span><br><span class="line"><span class="comment">            &lt;property name="sqlSessionTemplate" ref="sqlSession"&gt;&lt;/property&gt;</span></span><br><span class="line"><span class="comment">    &lt;/bean&gt;</span></span><br><span class="line"><span class="comment">     --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">class</span>=<span class="string">"org.mybatis.spring.mapper.MapperScannerConfigurer"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"basePackage"</span> <span class="attr">value</span>=<span class="string">"org.dao"</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--&lt;property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"&gt;&lt;/property&gt; --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"sqlSessionTemplateBeanName"</span> <span class="attr">value</span>=<span class="string">"sqlSession"</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 限定型操作，指定要进行寻找的注解名称或者接口名称 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"annotationClass"</span> <span class="attr">value</span>=<span class="string">"org.springframework.stereotype."</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"markerInterface"</span> <span class="attr">value</span>=<span class="string">"org.dao.xxxx"</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">beans</span>&gt;</span></span><br></pre></td></tr></table></figure>
<blockquote>
<p>javabean–org.user包</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> org.user;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"> </span><br><span class="line"><span class="meta">@Component</span>(<span class="string">"people"</span>)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">People</span> </span>&#123;</span><br><span class="line">	<span class="keyword">private</span> String name;</span><br><span class="line">	<span class="keyword">private</span> <span class="keyword">int</span> money;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> String <span class="title">getName</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">return</span> name;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setName</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">this</span>.name = name;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getMoney</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">return</span> money;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setMoney</span><span class="params">(<span class="keyword">int</span> money)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">this</span>.money = money;</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">package</span> org.user;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"> </span><br><span class="line"><span class="meta">@Component</span>(<span class="string">"jack"</span>)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Jack</span> <span class="keyword">extends</span> <span class="title">People</span></span>&#123;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="title">Jack</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="comment">// TODO Auto-generated constructor stub</span></span><br><span class="line">		<span class="keyword">this</span>.setName(<span class="string">"Jack"</span>);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">package</span> org.user;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"> </span><br><span class="line"><span class="meta">@Component</span>(<span class="string">"Tom"</span>)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Tom</span> <span class="keyword">extends</span> <span class="title">People</span> </span>&#123;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="title">Tom</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="comment">// TODO Auto-generated constructor stub</span></span><br><span class="line">		<span class="keyword">this</span>.setName(<span class="string">"Tom"</span>);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>mybatis映射接口-org.dao包</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> org.dao;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">import</span> org.apache.ibatis.annotations.Param;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Repository;</span><br><span class="line"><span class="keyword">import</span> org.user.People;</span><br><span class="line"> </span><br><span class="line"><span class="meta">@Repository</span>(<span class="string">"userMoney"</span>)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">UserMoney</span> </span>&#123;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">deductMoney</span><span class="params">(@Param(<span class="string">"money"</span>)</span><span class="keyword">int</span> money,@<span class="title">Param</span><span class="params">(<span class="string">"people"</span>)</span>People people)</span>;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">addMoney</span><span class="params">(@Param(<span class="string">"money"</span>)</span><span class="keyword">int</span> money,@<span class="title">Param</span><span class="params">(<span class="string">"people"</span>)</span>People people)</span>;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> List&lt;People&gt; <span class="title">showMoney</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这里要注意：mybatis参数传递的规则，默认只能传入一个类，如果是基本类型 使用#{xxx}(xxx为任意字段)就可以进行导入，如果是一个类#{xxx}(xxx为类中的任意属性)，当使用@Param注解时候，使用的时候必须相对应的名称（底层mybatis 把他参数变成map类型了）</p>
<blockquote>
<p>数据库应用服务类-org.service</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> org.Service;</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"><span class="keyword">import</span> javax.annotation.Resource;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">import</span> org.dao.UserMoney;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"><span class="keyword">import</span> org.springframework.transaction.annotation.Isolation;</span><br><span class="line"><span class="keyword">import</span> org.springframework.transaction.annotation.Propagation;</span><br><span class="line"><span class="keyword">import</span> org.springframework.transaction.annotation.Transactional;</span><br><span class="line"><span class="keyword">import</span> org.user.People;</span><br><span class="line"><span class="meta">@Component</span>(<span class="string">"moneyService"</span>)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MoneyService</span> </span>&#123;</span><br><span class="line">	<span class="meta">@Resource</span>(name=<span class="string">"userMoney"</span>)</span><br><span class="line">	<span class="keyword">public</span> UserMoney userMoney;</span><br><span class="line">	<span class="meta">@Transactional</span>(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED)</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">okStart</span><span class="params">(People from,People to)</span> </span>&#123;</span><br><span class="line">		userMoney.addMoney(from.getMoney(), from);</span><br><span class="line">		userMoney.deductMoney(to.getMoney(), to);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>main函数</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> org;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">import</span> org.Service.MoneyService;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.ApplicationContext;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.support.ClassPathXmlApplicationContext;</span><br><span class="line"><span class="keyword">import</span> org.user.Jack;</span><br><span class="line"><span class="keyword">import</span> org.user.Tom;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">		<span class="comment">// TODO Auto-generated constructor stub</span></span><br><span class="line">		ApplicationContext context=<span class="keyword">new</span> ClassPathXmlApplicationContext(<span class="string">"bean.xml"</span>);</span><br><span class="line">		MoneyService service = context.getBean(<span class="string">"moneyService"</span>,MoneyService.class);</span><br><span class="line">		Tom tom = <span class="keyword">new</span> Tom();</span><br><span class="line">		tom.setMoney(<span class="number">1000</span>);</span><br><span class="line">		Jack jack = <span class="keyword">new</span> Jack();</span><br><span class="line">		jack.setMoney(<span class="number">1000</span>);</span><br><span class="line">		service.okStart(tom, jack);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2018/10/09/深入理解mybatis（九）mybatis运行原理和分析/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="kyssion">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="kyssion-blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2018/10/09/深入理解mybatis（九）mybatis运行原理和分析/" itemprop="url">未命名</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-10-09T15:22:37+08:00">
                2018-10-09
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h3 id="mybatis-构建过程"><a href="#mybatis-构建过程" class="headerlink" title="mybatis 构建过程"></a>mybatis 构建过程</h3><h4 id="sessionfactory-构建sqlsession"><a href="#sessionfactory-构建sqlsession" class="headerlink" title="sessionfactory 构建sqlsession"></a>sessionfactory 构建sqlsession</h4><p>mybatis 使用sqlSession同数据库进行相关的操作所以在使用之前需要获取这个类，在mybatis 中使用sessionfactory 进行</p>
<p>通常情况下，mybatis使用的是SqlSessionFactoryBuilder的builder方法获取sessionfacotry ，其实这是一种封装，查看源代码可知，其实他是封装了一个DefaultSqlSessionFactory类,通过传入的Config进行初始化的</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SqlSessionFactoryBuilder</span> </span>&#123;</span><br><span class="line">  <span class="function"><span class="keyword">public</span> SqlSessionFactory <span class="title">build</span><span class="params">(Reader reader)</span> </span>&#123;<span class="keyword">return</span> build(reader, <span class="keyword">null</span>, <span class="keyword">null</span>);&#125;</span><br><span class="line">  <span class="function"><span class="keyword">public</span> SqlSessionFactory <span class="title">build</span><span class="params">(Reader reader, String environment)</span> </span>&#123;<span class="keyword">return</span> build(reader, environment, <span class="keyword">null</span>);&#125;</span><br><span class="line">  <span class="function"><span class="keyword">public</span> SqlSessionFactory <span class="title">build</span><span class="params">(Reader reader, Properties properties)</span> </span>&#123;<span class="keyword">return</span> build(reader, <span class="keyword">null</span>, properties);&#125;</span><br><span class="line">  <span class="function"><span class="keyword">public</span> SqlSessionFactory <span class="title">build</span><span class="params">(InputStream inputStream)</span> </span>&#123;<span class="keyword">return</span> build(inputStream, <span class="keyword">null</span>, <span class="keyword">null</span>);&#125;</span><br><span class="line">  <span class="function"><span class="keyword">public</span> SqlSessionFactory <span class="title">build</span><span class="params">(InputStream inputStream, String environment)</span> </span>&#123;<span class="keyword">return</span> build(inputStream, environment, <span class="keyword">null</span>);&#125;</span><br><span class="line">  <span class="function"><span class="keyword">public</span> SqlSessionFactory <span class="title">build</span><span class="params">(InputStream inputStream, Properties properties)</span> </span>&#123;<span class="keyword">return</span> build(inputStream, <span class="keyword">null</span>, properties);&#125;</span><br><span class="line">  <span class="function"><span class="keyword">public</span> SqlSessionFactory <span class="title">build</span><span class="params">(Reader reader, String environment, Properties properties)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      XMLConfigBuilder parser = <span class="keyword">new</span> XMLConfigBuilder(reader, environment, properties);</span><br><span class="line">      <span class="keyword">return</span> build(parser.parse());</span><br><span class="line">    &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">      <span class="keyword">throw</span> ExceptionFactory.wrapException(<span class="string">"Error building SqlSession."</span>, e);</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">      ErrorContext.instance().reset();</span><br><span class="line">      <span class="keyword">try</span> &#123;</span><br><span class="line">        reader.close();</span><br><span class="line">      &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">        <span class="comment">// Intentionally ignore. Prefer previous error.</span></span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="function"><span class="keyword">public</span> SqlSessionFactory <span class="title">build</span><span class="params">(InputStream inputStream, String environment, Properties properties)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      XMLConfigBuilder parser = <span class="keyword">new</span> XMLConfigBuilder(inputStream, environment, properties);</span><br><span class="line">      <span class="keyword">return</span> build(parser.parse());</span><br><span class="line">    &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">      <span class="keyword">throw</span> ExceptionFactory.wrapException(<span class="string">"Error building SqlSession."</span>, e);</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">      ErrorContext.instance().reset();</span><br><span class="line">      <span class="keyword">try</span> &#123;</span><br><span class="line">        inputStream.close();</span><br><span class="line">      &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">        <span class="comment">// Intentionally ignore. Prefer previous error.</span></span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125; </span><br><span class="line">  <span class="function"><span class="keyword">public</span> SqlSessionFactory <span class="title">build</span><span class="params">(Configuration config)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> DefaultSqlSessionFactory(config);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>其实通过上面的分析就能知道其实在使用的Configuration类（这个类包含了mybatis几乎所有的配置），来初始化SqlSessionfacotory的</p>
</blockquote>
<h4 id="configuration对象"><a href="#configuration对象" class="headerlink" title="configuration对象"></a>configuration对象</h4><p>mybatis总体的配置文件包括如下的部分</p>
<ul>
<li>propertise：参数名称</li>
<li>setting ：设置</li>
<li>typeAliases：别名</li>
<li>typeHandler：类型处理器</li>
<li>ObjectFacotry: 返回值处理工厂对象</li>
<li>plugin：插件</li>
<li>enviroment：环境变量</li>
<li>DataBaseIdProivder：数据库标识</li>
<li>Mapper：映射器</li>
</ul>
<h3 id="mybatis最核心运行过程SqlSession"><a href="#mybatis最核心运行过程SqlSession" class="headerlink" title="mybatis最核心运行过程SqlSession"></a>mybatis最核心运行过程SqlSession</h3><p>首先看一下SqlSession这个接口的源代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">SqlSession</span> <span class="keyword">extends</span> <span class="title">Closeable</span> </span>&#123;</span><br><span class="line">    &lt;T&gt; <span class="function">T <span class="title">selectOne</span><span class="params">(String statement)</span></span>;</span><br><span class="line">    &lt;T&gt; <span class="function">T <span class="title">selectOne</span><span class="params">(String statement, Object parameter)</span></span>;</span><br><span class="line">    。。。。。</span><br><span class="line">    &lt;T&gt; <span class="function">T <span class="title">getMapper</span><span class="params">(Class&lt;T&gt; type)</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>SqlSession定义了对数据库的基本操作，CURD操作，其中有一个方法需要注意getMapper 这个方法将会返回一个Mapper接口对象，通过这个对象的方法就可以进行增删改从而并不需要使用原来的方法进行处理,mapper此时就成为操作数据库的方法了，接下来分析一下mapper</p>
<h4 id="深入分析mapper初始化机制"><a href="#深入分析mapper初始化机制" class="headerlink" title="深入分析mapper初始化机制"></a>深入分析mapper初始化机制</h4><blockquote>
<p>mybatis的mapper是在一开始的时候就通过config就生成了</p>
</blockquote>
<p>留心configuration 对象中的mapperRegistry 这个属性的对象，mybatis初始化所有的mapper都储存在这个对象之中</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Configuration</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">addMappers</span><span class="params">(String packageName, Class&lt;?&gt; superType)</span> </span>&#123;</span><br><span class="line">        mapperRegistry.addMappers(packageName, superType);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">addMappers</span><span class="params">(String packageName)</span> </span>&#123;</span><br><span class="line">        mapperRegistry.addMappers(packageName);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">public</span> &lt;T&gt; <span class="function"><span class="keyword">void</span> <span class="title">addMapper</span><span class="params">(Class&lt;T&gt; type)</span> </span>&#123;</span><br><span class="line">        mapperRegistry.addMapper(type);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>跟进addMapper方法可以发现，这个方法的处理方式其实是让class作为健，生成一个新的代理对象MapperProxyFactory作为值值存入knownMappers这个HashMap</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> &lt;T&gt; <span class="function"><span class="keyword">void</span> <span class="title">addMapper</span><span class="params">(Class&lt;T&gt; type)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (type.isInterface()) &#123;</span><br><span class="line">        <span class="keyword">if</span> (hasMapper(type)) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> BindingException(<span class="string">"Type "</span> + type + <span class="string">" is already known to the MapperRegistry."</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">boolean</span> loadCompleted = <span class="keyword">false</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            knownMappers.put(type, <span class="keyword">new</span> MapperProxyFactory&lt;T&gt;(type));</span><br><span class="line">            <span class="comment">// It's important that the type is added before the parser is run</span></span><br><span class="line">            <span class="comment">// otherwise the binding may automatically be attempted by the</span></span><br><span class="line">            <span class="comment">// mapper parser. If the type is already known, it won't try.</span></span><br><span class="line">            MapperAnnotationBuilder parser = <span class="keyword">new</span> MapperAnnotationBuilder(config, type);</span><br><span class="line">            parser.parse();</span><br><span class="line">            loadCompleted = <span class="keyword">true</span>;</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> (!loadCompleted) &#123;</span><br><span class="line">                knownMappers.remove(type);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="深入分析mapper的初始化调用机制"><a href="#深入分析mapper的初始化调用机制" class="headerlink" title="深入分析mapper的初始化调用机制"></a>深入分析mapper的初始化调用机制</h4><p>在SqlSession.getMapper获取Mapper的时候同样是通过这个方式反方向方法获取MapperProxyFactory这个对象</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> &lt;T&gt; <span class="function">T <span class="title">getMapper</span><span class="params">(Class&lt;T&gt; type, SqlSession sqlSession)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">final</span> MapperProxyFactory&lt;T&gt; mapperProxyFactory = (MapperProxyFactory&lt;T&gt;) knownMappers.get(type);</span><br><span class="line">    <span class="keyword">if</span> (mapperProxyFactory == <span class="keyword">null</span>) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> BindingException(<span class="string">"Type "</span> + type + <span class="string">" is not known to the MapperRegistry."</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> mapperProxyFactory.newInstance(sqlSession);</span><br><span class="line">    &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> BindingException(<span class="string">"Error getting mapper instance. Cause: "</span> + e, e);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>从代码中可以看看出来其实此时使用的mapper是通过proxyfactory生成的代理对象</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MapperProxyFactory</span>&lt;<span class="title">T</span>&gt; </span>&#123;</span><br><span class="line">  。。。</span><br><span class="line">  <span class="function"><span class="keyword">protected</span> T <span class="title">newInstance</span><span class="params">(MapperProxy&lt;T&gt; mapperProxy)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), <span class="keyword">new</span> Class[] &#123; mapperInterface &#125;, mapperProxy);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="function"><span class="keyword">public</span> T <span class="title">newInstance</span><span class="params">(SqlSession sqlSession)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">final</span> MapperProxy&lt;T&gt; mapperProxy = <span class="keyword">new</span> MapperProxy&lt;T&gt;(sqlSession, mapperInterface, methodCache);</span><br><span class="line">    <span class="keyword">return</span> newInstance(mapperProxy);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>我们都知道代理是指定invoke方法来实现回调的这里我们跟进一下看一下mapperProxy的代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MapperProxy</span>&lt;<span class="title">T</span>&gt; <span class="keyword">implements</span> <span class="title">InvocationHandler</span>, <span class="title">Serializable</span> </span>&#123;</span><br><span class="line">  <span class="meta">@Override</span></span><br><span class="line">  <span class="function"><span class="keyword">public</span> Object <span class="title">invoke</span><span class="params">(Object proxy, Method method, Object[] args)</span> <span class="keyword">throws</span> Throwable </span>&#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      <span class="keyword">if</span> (Object.class.equals(method.getDeclaringClass())) &#123;</span><br><span class="line">        <span class="keyword">return</span> method.invoke(<span class="keyword">this</span>, args);</span><br><span class="line">      &#125; <span class="keyword">else</span> <span class="keyword">if</span> (isDefaultMethod(method)) &#123;</span><br><span class="line">        <span class="keyword">return</span> invokeDefaultMethod(proxy, method, args);</span><br><span class="line">      &#125;</span><br><span class="line">    &#125; <span class="keyword">catch</span> (Throwable t) &#123;</span><br><span class="line">      <span class="keyword">throw</span> ExceptionUtil.unwrapThrowable(t);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">final</span> MapperMethod mapperMethod = cachedMapperMethod(method);</span><br><span class="line">    <span class="keyword">return</span> mapperMethod.execute(sqlSession, args);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>其实跟踪到这里已经非常明确的 其实他是使用了mapperMethod.execute(sqlSession, args)来执行语句，看一下</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> Object <span class="title">execute</span><span class="params">(SqlSession sqlSession, Object[] args)</span> </span>&#123;</span><br><span class="line">    Object result;</span><br><span class="line">    <span class="keyword">switch</span> (command.getType()) &#123;</span><br><span class="line">      <span class="keyword">case</span> INSERT: &#123;</span><br><span class="line">      Object param = method.convertArgsToSqlCommandParam(args);</span><br><span class="line">        result = rowCountResult(sqlSession.insert(command.getName(), param));</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">      &#125;</span><br><span class="line">     。。。。。</span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>
<p>代码逻辑非常清晰其实就是使用sqlSession的对应方法，mapper的报名加上类名构成了一开始的名称</p>
<p>####　分析SqlSession运行相关数据库操作的详细分析</p>
<p>通过源代码分析其实最终情况下sql将操作分成了两种类型 doupdate类型和query这里先看一下query</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> &lt;E&gt; <span class="function">List&lt;E&gt; <span class="title">query</span><span class="params">(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)</span> <span class="keyword">throws</span> SQLException </span>&#123;</span><br><span class="line">  ErrorContext.instance().resource(ms.getResource()).activity(<span class="string">"executing a query"</span>).object(ms.getId());</span><br><span class="line"><span class="comment">//如果已经关闭，报错</span></span><br><span class="line">  <span class="keyword">if</span> (closed) <span class="keyword">throw</span> <span class="keyword">new</span> ExecutorException(<span class="string">"Executor was closed."</span>);</span><br><span class="line"><span class="comment">//先清局部缓存，再查询，但仅仅查询堆栈为0才清，为了处理递归调用</span></span><br><span class="line">  <span class="keyword">if</span> (queryStack == <span class="number">0</span> &amp;&amp; ms.isFlushCacheRequired()) &#123;</span><br><span class="line">    clearLocalCache();</span><br><span class="line">  &#125;</span><br><span class="line">  List&lt;E&gt; list;</span><br><span class="line">  <span class="keyword">try</span> &#123;</span><br><span class="line">  <span class="comment">//加一，这样递归调用到上面的时候就不会再清局部缓存了</span></span><br><span class="line">    queryStack++;</span><br><span class="line">  <span class="comment">//根据cachekey从localCache去查</span></span><br><span class="line">    list = resultHandler == <span class="keyword">null</span> ? (List&lt;E&gt;) localCache.getObject(key) : <span class="keyword">null</span>;</span><br><span class="line">    <span class="keyword">if</span> (list != <span class="keyword">null</span>) &#123;</span><br><span class="line">  <span class="comment">//如果查到localCache缓存，处理localOutputParameterCache</span></span><br><span class="line">      handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">  <span class="comment">//从数据库查</span></span><br><span class="line">      list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">  <span class="comment">//清空堆栈</span></span><br><span class="line">    queryStack--;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">if</span> (queryStack == <span class="number">0</span>) &#123;</span><br><span class="line">  <span class="comment">//延迟加载队列中所有元素</span></span><br><span class="line">    <span class="keyword">for</span> (DeferredLoad deferredLoad : deferredLoads) &#123;</span><br><span class="line">      deferredLoad.load();</span><br><span class="line">    &#125;</span><br><span class="line">  <span class="comment">//清空延迟加载队列</span></span><br><span class="line">    deferredLoads.clear(); <span class="comment">// issue #601</span></span><br><span class="line">    <span class="keyword">if</span> (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) &#123;</span><br><span class="line">  <span class="comment">//如果是statement，清本地缓存</span></span><br><span class="line">      clearLocalCache(); <span class="comment">// issue #482</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> list;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>真正执行相关的query操作的方法是deQuery方法(executor类的doQuery)</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> &lt;E&gt; <span class="function">List&lt;E&gt; <span class="title">doQuery</span><span class="params">(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql)</span> <span class="keyword">throws</span> SQLException </span>&#123;</span><br><span class="line">  Statement stmt = <span class="keyword">null</span>;</span><br><span class="line">  <span class="keyword">try</span> &#123;</span><br><span class="line">    Configuration configuration = ms.getConfiguration();</span><br><span class="line">    StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);</span><br><span class="line">    stmt = prepareStatement(handler, ms.getStatementLog());</span><br><span class="line">    <span class="keyword">return</span> handler.&lt;E&gt;query(stmt, resultHandler);</span><br><span class="line">  &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">    closeStatement(stmt);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>从上面的方法中我们可以看见一个方法叫MappedStatement,观察一下他的产生</p>
<h4 id="MappedStatement-产生过程"><a href="#MappedStatement-产生过程" class="headerlink" title="MappedStatement 产生过程"></a>MappedStatement 产生过程</h4><p>通过获取方法可以判断出,这个类其实是一开就在configration配置成功的</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">MappedStatement ms = configuration.getMappedStatement(statement);</span><br></pre></td></tr></table></figure>
<p>如果跟踪一开始初始化的状态需要跟踪到SqlSessionFactoryBuilder类中,一开始mybatiss将所有状态初始化的过程</p>
<p>SqlSessionFactoryBuilder在默认情况下会使用XMLConfigBuilder来生成configration</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> SqlSessionFactory <span class="title">build</span><span class="params">(Reader reader, String environment, Properties properties)</span> </span>&#123;</span><br><span class="line">  XMLConfigBuilder parser = <span class="keyword">new</span> XMLConfigBuilder(reader, environment, properties);</span><br><span class="line">  <span class="keyword">return</span> build(parser.parse());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>接下来跟踪进去发现了初始化一个类XPathParser,并且使用嵌套构造函数的方法进行方法嵌套使用</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="title">XMLConfigBuilder</span><span class="params">(Reader reader, String environment, Properties props)</span> </span>&#123;</span><br><span class="line">  <span class="keyword">this</span>(<span class="keyword">new</span> XPathParser(reader, <span class="keyword">true</span>, props, <span class="keyword">new</span> XMLMapperEntityResolver()), environment, props);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="title">XMLConfigBuilder</span><span class="params">(XPathParser parser, String environment, Properties props)</span> </span>&#123;</span><br><span class="line">  <span class="keyword">super</span>(<span class="keyword">new</span> Configuration());</span><br><span class="line">  ErrorContext.instance().resource(<span class="string">"SQL Mapper Configuration"</span>);</span><br><span class="line">  <span class="keyword">this</span>.configuration.setVariables(props);</span><br><span class="line">  <span class="keyword">this</span>.parsed = <span class="keyword">false</span>;</span><br><span class="line">  <span class="keyword">this</span>.environment = environment;</span><br><span class="line">  <span class="keyword">this</span>.parser = parser;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>这个类其实就是将xml文件整理成node节点的形式方便之后的调用,其实是一个解析用的工具</p>
</blockquote>
<p>然后上调用者(sqlSessionFactoryBuilder)将会调用XMLConfigBuilder的parse方法进行生产configration对象这里才是整个mybatis配置真正产生的地方</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> Configuration <span class="title">parse</span><span class="params">()</span> </span>&#123;</span><br><span class="line">  <span class="keyword">if</span> (parsed) &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> BuilderException(<span class="string">"Each XMLConfigBuilder can only be used once."</span>);</span><br><span class="line">  &#125;</span><br><span class="line">  parsed = <span class="keyword">true</span>;</span><br><span class="line">  parseConfiguration(parser.evalNode(<span class="string">"/configuration"</span>));</span><br><span class="line">  <span class="keyword">return</span> configuration;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//所有的配置都是在这里生成的</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">parseConfiguration</span><span class="params">(XNode root)</span> </span>&#123;</span><br><span class="line">  <span class="keyword">try</span> &#123;</span><br><span class="line">    <span class="comment">//issue #117 read properties first</span></span><br><span class="line">    propertiesElement(root.evalNode(<span class="string">"properties"</span>));</span><br><span class="line">    Properties settings = settingsAsProperties(root.evalNode(<span class="string">"settings"</span>));</span><br><span class="line">    loadCustomVfs(settings);</span><br><span class="line">    typeAliasesElement(root.evalNode(<span class="string">"typeAliases"</span>));</span><br><span class="line">    pluginElement(root.evalNode(<span class="string">"plugins"</span>));</span><br><span class="line">    objectFactoryElement(root.evalNode(<span class="string">"objectFactory"</span>));</span><br><span class="line">    objectWrapperFactoryElement(root.evalNode(<span class="string">"objectWrapperFactory"</span>));</span><br><span class="line">    reflectorFactoryElement(root.evalNode(<span class="string">"reflectorFactory"</span>));</span><br><span class="line">    settingsElement(settings);</span><br><span class="line">    <span class="comment">// read it after objectFactory and objectWrapperFactory issue #631</span></span><br><span class="line">    environmentsElement(root.evalNode(<span class="string">"environments"</span>));</span><br><span class="line">    databaseIdProviderElement(root.evalNode(<span class="string">"databaseIdProvider"</span>));</span><br><span class="line">    typeHandlerElement(root.evalNode(<span class="string">"typeHandlers"</span>));</span><br><span class="line">    mapperElement(root.evalNode(<span class="string">"mappers"</span>));</span><br><span class="line">  &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> BuilderException(<span class="string">"Error parsing SQL Mapper Configuration. Cause: "</span> + e, e);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>终于到了关键的地方MappedStatement的生成部分,MappedStatement由名称就能知道是从mapperElement()方法中产生的</p>
<p>在XMLConfigBuilder中定义的这个方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">mapperElement</span><span class="params">(XNode parent)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">  <span class="keyword">if</span> (parent != <span class="keyword">null</span>) &#123;</span><br><span class="line">    <span class="keyword">for</span> (XNode child : parent.getChildren()) &#123;</span><br><span class="line">      <span class="keyword">if</span> (<span class="string">"package"</span>.equals(child.getName())) &#123;</span><br><span class="line">        String mapperPackage = child.getStringAttribute(<span class="string">"name"</span>);</span><br><span class="line">        configuration.addMappers(mapperPackage);</span><br><span class="line">      &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>我截取了一段代码这段代码是处理使用包名扫描mapper的代码,进入到其中的configuration.addMappers(mapperPackage);方法,发现这里使用了configration中的addMappers方法,进入到mapperRegistry类的这个方法中</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">addMappers</span><span class="params">(String packageName)</span> </span>&#123;</span><br><span class="line">  mapperRegistry.addMappers(packageName);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>跟踪到这里其实思路比较清晰了,这里就是初始化一个mapper和mapper中各种mathod的地方（MapperRegistry）</p>
<blockquote>
<p>注意到MapperStatues和Method是一一对应的</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> &lt;T&gt; <span class="function"><span class="keyword">void</span> <span class="title">addMapper</span><span class="params">(Class&lt;T&gt; type)</span> </span>&#123;</span><br><span class="line">  <span class="keyword">if</span> (type.isInterface()) &#123;</span><br><span class="line">    <span class="keyword">if</span> (hasMapper(type)) &#123;</span><br><span class="line">      <span class="keyword">throw</span> <span class="keyword">new</span> BindingException(<span class="string">"Type "</span> + type + <span class="string">" is already known to the MapperRegistry."</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">boolean</span> loadCompleted = <span class="keyword">false</span>;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      knownMappers.put(type, <span class="keyword">new</span> MapperProxyFactory&lt;T&gt;(type));</span><br><span class="line">      MapperAnnotationBuilder parser = <span class="keyword">new</span> MapperAnnotationBuilder(config, type);</span><br><span class="line">      parser.parse();</span><br><span class="line">      loadCompleted = <span class="keyword">true</span>;</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">      <span class="keyword">if</span> (!loadCompleted) &#123;</span><br><span class="line">        knownMappers.remove(type);</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>而MappedStatement的初始化就在这个MapperAnnotationBuilder.parse()</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">parse</span><span class="params">()</span> </span>&#123;</span><br><span class="line">  String resource = type.toString();</span><br><span class="line">  <span class="keyword">if</span> (!configuration.isResourceLoaded(resource)) &#123;</span><br><span class="line">    loadXmlResource();</span><br><span class="line">    configuration.addLoadedResource(resource);</span><br><span class="line">    assistant.setCurrentNamespace(type.getName());</span><br><span class="line">    parseCache();</span><br><span class="line">    parseCacheRef();</span><br><span class="line">    Method[] methods = type.getMethods();</span><br><span class="line">    <span class="keyword">for</span> (Method method : methods) &#123;</span><br><span class="line">      <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">// issue #237</span></span><br><span class="line">        <span class="keyword">if</span> (!method.isBridge()) &#123;</span><br><span class="line">          parseStatement(method);</span><br><span class="line">        &#125;</span><br><span class="line">      &#125; <span class="keyword">catch</span> (IncompleteElementException e) &#123;</span><br><span class="line">        configuration.addIncompleteMethod(<span class="keyword">new</span> MethodResolver(<span class="keyword">this</span>, method));</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  parsePendingMethods();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">parseStatement</span><span class="params">(Method method)</span> </span>&#123;</span><br><span class="line">  Class&lt;?&gt; parameterTypeClass = getParameterType(method);</span><br><span class="line">  LanguageDriver languageDriver = getLanguageDriver(method);</span><br><span class="line">  SqlSource sqlSource = getSqlSourceFromAnnotations(method, parameterTypeClass, languageDriver);</span><br><span class="line">  <span class="keyword">if</span> (sqlSource != <span class="keyword">null</span>) &#123;</span><br><span class="line">    Options options = method.getAnnotation(Options.class);</span><br><span class="line">    <span class="keyword">final</span> String mappedStatementId = type.getName() + <span class="string">"."</span> + method.getName();</span><br><span class="line">    Integer fetchSize = <span class="keyword">null</span>;</span><br><span class="line">    Integer timeout = <span class="keyword">null</span>;</span><br><span class="line">    StatementType statementType = StatementType.PREPARED;</span><br><span class="line">    ResultSetType resultSetType = ResultSetType.FORWARD_ONLY;</span><br><span class="line">    SqlCommandType sqlCommandType = getSqlCommandType(method);</span><br><span class="line">    <span class="keyword">boolean</span> isSelect = sqlCommandType == SqlCommandType.SELECT;</span><br><span class="line">    <span class="keyword">boolean</span> flushCache = !isSelect;</span><br><span class="line">    <span class="keyword">boolean</span> useCache = isSelect;</span><br><span class="line">    KeyGenerator keyGenerator;</span><br><span class="line">    String keyProperty = <span class="string">"id"</span>;</span><br><span class="line">    String keyColumn = <span class="keyword">null</span>;</span><br><span class="line">    <span class="keyword">if</span> (SqlCommandType.INSERT.equals(sqlCommandType) || SqlCommandType.UPDATE.equals(sqlCommandType)) &#123;</span><br><span class="line">      <span class="comment">// first check for SelectKey annotation - that overrides everything else</span></span><br><span class="line">      SelectKey selectKey = method.getAnnotation(SelectKey.class);</span><br><span class="line">      <span class="keyword">if</span> (selectKey != <span class="keyword">null</span>) &#123;</span><br><span class="line">        keyGenerator = handleSelectKeyAnnotation(selectKey, mappedStatementId, getParameterType(method), languageDriver);</span><br><span class="line">        keyProperty = selectKey.keyProperty();</span><br><span class="line">      &#125; <span class="keyword">else</span> <span class="keyword">if</span> (options == <span class="keyword">null</span>) &#123;</span><br><span class="line">        keyGenerator = configuration.isUseGeneratedKeys() ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE;</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        keyGenerator = options.useGeneratedKeys() ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE;</span><br><span class="line">        keyProperty = options.keyProperty();</span><br><span class="line">        keyColumn = options.keyColumn();</span><br><span class="line">      &#125;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      keyGenerator = NoKeyGenerator.INSTANCE;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (options != <span class="keyword">null</span>) &#123;</span><br><span class="line">      <span class="keyword">if</span> (FlushCachePolicy.TRUE.equals(options.flushCache())) &#123;</span><br><span class="line">        flushCache = <span class="keyword">true</span>;</span><br><span class="line">      &#125; <span class="keyword">else</span> <span class="keyword">if</span> (FlushCachePolicy.FALSE.equals(options.flushCache())) &#123;</span><br><span class="line">        flushCache = <span class="keyword">false</span>;</span><br><span class="line">      &#125;</span><br><span class="line">      useCache = options.useCache();</span><br><span class="line">      fetchSize = options.fetchSize() &gt; -<span class="number">1</span> || options.fetchSize() == Integer.MIN_VALUE ? options.fetchSize() : <span class="keyword">null</span>; <span class="comment">//issue #348</span></span><br><span class="line">      timeout = options.timeout() &gt; -<span class="number">1</span> ? options.timeout() : <span class="keyword">null</span>;</span><br><span class="line">      statementType = options.statementType();</span><br><span class="line">      resultSetType = options.resultSetType();</span><br><span class="line">    &#125;</span><br><span class="line">    String resultMapId = <span class="keyword">null</span>;</span><br><span class="line">    ResultMap resultMapAnnotation = method.getAnnotation(ResultMap.class);</span><br><span class="line">    <span class="keyword">if</span> (resultMapAnnotation != <span class="keyword">null</span>) &#123;</span><br><span class="line">      String[] resultMaps = resultMapAnnotation.value();</span><br><span class="line">      StringBuilder sb = <span class="keyword">new</span> StringBuilder();</span><br><span class="line">      <span class="keyword">for</span> (String resultMap : resultMaps) &#123;</span><br><span class="line">        <span class="keyword">if</span> (sb.length() &gt; <span class="number">0</span>) &#123;</span><br><span class="line">          sb.append(<span class="string">","</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        sb.append(resultMap);</span><br><span class="line">      &#125;</span><br><span class="line">      resultMapId = sb.toString();</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (isSelect) &#123;</span><br><span class="line">      resultMapId = parseResultMap(method);</span><br><span class="line">    &#125;</span><br><span class="line">    assistant.addMappedStatement(</span><br><span class="line">        mappedStatementId,</span><br><span class="line">        sqlSource,</span><br><span class="line">        statementType,</span><br><span class="line">        sqlCommandType,</span><br><span class="line">        fetchSize,</span><br><span class="line">        timeout,</span><br><span class="line">        <span class="comment">// ParameterMapID</span></span><br><span class="line">        <span class="keyword">null</span>,</span><br><span class="line">        parameterTypeClass,</span><br><span class="line">        resultMapId,</span><br><span class="line">        getReturnType(method),</span><br><span class="line">        resultSetType,</span><br><span class="line">        flushCache,</span><br><span class="line">        useCache,</span><br><span class="line">        <span class="comment">// TODO gcode issue #577</span></span><br><span class="line">        <span class="keyword">false</span>,</span><br><span class="line">        keyGenerator,</span><br><span class="line">        keyProperty,</span><br><span class="line">        keyColumn,</span><br><span class="line">        <span class="comment">// DatabaseID</span></span><br><span class="line">        <span class="keyword">null</span>,</span><br><span class="line">        languageDriver,</span><br><span class="line">        <span class="comment">// ResultSets</span></span><br><span class="line">        options != <span class="keyword">null</span> ? nullOrEmpty(options.resultSets()) : <span class="keyword">null</span>);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>从上面我们就可以得出MapperStatement的作用就是配置一个sql的各种信息，比如操作方法（select|upadte等），配置的sql ， sql的id ，缓存信息，resultMap，parameterType，resultType，languageDriver，等</p>

          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2018/10/09/深入理解mybatis（三）高级映射文件/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="kyssion">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="kyssion-blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2018/10/09/深入理解mybatis（三）高级映射文件/" itemprop="url">未命名</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-10-09T15:22:37+08:00">
                2018-10-09
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h2 id="深入理解mybatis（三）高级映射文件"><a href="#深入理解mybatis（三）高级映射文件" class="headerlink" title="深入理解mybatis（三）高级映射文件"></a>深入理解mybatis（三）高级映射文件</h2><p>mybatis高级部分解决各种高级映射问题</p>
<h3 id="association-一对一关联"><a href="#association-一对一关联" class="headerlink" title="association 一对一关联"></a>association 一对一关联</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">association</span> <span class="attr">property</span>=<span class="string">"author"</span> <span class="attr">column</span>=<span class="string">"blog_author_id"</span> <span class="attr">javaType</span>=<span class="string">"Author"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">id</span> <span class="attr">property</span>=<span class="string">"id"</span> <span class="attr">column</span>=<span class="string">"author_id"</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"username"</span> <span class="attr">column</span>=<span class="string">"author_username"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">association</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>关联中不同的是你需要告诉 MyBatis 如何加载关联。MyBatis 在这方面会有两种不同的 方式:</p>
<ul>
<li>嵌套查询:通过执行另外一个 SQL 映射语句来返回预期的复杂类型。</li>
<li>嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集。<br>基本属性（和id和resultful相同）</li>
</ul>
<table>
<thead>
<tr>
<th>参数属性</th>
<th>属性信息</th>
</tr>
</thead>
<tbody>
<tr>
<td>property</td>
<td>映射到列结果的字段或属性。如果匹配的是存在的,和给定名称相同的 property JavaBeans 的属性, 那么就会使用。否则 MyBatis 将会寻找给定名称的字段。 这两种情形你可以使用通常点式的复杂属性导航。比如,你可以这样映射 一 些 东 西 :“ username ”, 或 者 映 射 到 一 些 复 杂 的 东 西 : “address.street.number” 。</td>
</tr>
<tr>
<td>javaType</td>
<td>一个Java 类的完全限定名,或一个类型别名(参考上面内建类型别名的列 表) 。如果你映射到一个 JavaBean,MyBatis 通常可以断定类型。然而,如 javaType 果你映射到的是 HashMap,那么你应该明确地指定 javaType 来保证所需的 行为。</td>
</tr>
<tr>
<td>jdbcType</td>
<td>在这个表格之前的所支持的 JDBC 类型列表中的类型。JDBC 类型是仅仅 需要对插入, 更新和删除操作可能为空的列进行处理。这是 JDBC 的需要, jdbcType 而不是 MyBatis 的。如果你直接使用 JDBC 编程,你需要指定这个类型-但 仅仅对可能为空的值。</td>
</tr>
<tr>
<td>typeHandler</td>
<td>我们在前面讨论过默认的类型处理器。使用这个属性,你可以覆盖默认的 typeHandler 类型处理器。 这个属性值是类的完全限定名或者是一个类型处理器的实现, 或者是类型别名。</td>
</tr>
</tbody>
</table>
<h3 id="使用嵌套查询方法"><a href="#使用嵌套查询方法" class="headerlink" title="使用嵌套查询方法"></a>使用嵌套查询方法</h3><table>
<thead>
<tr>
<th>参数属性</th>
<th>属性信息</th>
</tr>
</thead>
<tbody>
<tr>
<td>column</td>
<td>来自数据库的类名,或重命名的列标签。这和通常传递给 resultSet.getString(columnName)方法的字符串是相同的。 column 注 意 : 要 处 理 复 合 主 键 , 你 可 以 指 定 多 个 列 名 通 过 column= ” {prop1=col1,prop2=col2} ” 这种语法来传递给嵌套查询语 句。这会引起 prop1 和 prop2 以参数对象形式来设置给目标嵌套查询语句。</td>
</tr>
<tr>
<td>select</td>
<td>另外一个映射语句的 ID,可以加载这个属性映射需要的复杂类型。获取的 在列属性中指定的列的值将被传递给目标 select 语句作为参数。表格后面 有一个详细的示例。select 注 意 : 要 处 理 复 合 主 键 , 你 可 以 指 定 多 个 列 名 通 过 column= ” {prop1=col1,prop2=col2} ” 这种语法来传递给嵌套查询语 句。这会引起 prop1 和 prop2 以参数对象形式来设置给目标嵌套查询语句。</td>
</tr>
<tr>
<td>fetchType</td>
<td>可选的。有效值为 lazy和eager。如果使用了，它将取代全局配置参数lazyLoadingEnabled。</td>
</tr>
</tbody>
</table>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">resultMap</span> <span class="attr">id</span>=<span class="string">"blogResult"</span> <span class="attr">type</span>=<span class="string">"Blog"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">association</span> <span class="attr">property</span>=<span class="string">"author"</span> <span class="attr">column</span>=<span class="string">"author_id"</span> <span class="attr">javaType</span>=<span class="string">"Author"</span> <span class="attr">select</span>=<span class="string">"selectAuthor"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resultMap</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">"selectBlog"</span> <span class="attr">resultMap</span>=<span class="string">"blogResult"</span>&gt;</span></span><br><span class="line">    SELECT * FROM BLOG WHERE ID = #&#123;id&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">"selectAuthor"</span> <span class="attr">resultType</span>=<span class="string">"Author"</span>&gt;</span></span><br><span class="line">    SELECT * FROM AUTHOR WHERE ID = #&#123;id&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>这种方式很简单, 但是对于大型数据集合和列表将不会表现很好。 问题就是我们熟知的 “N+1 查询问题”。概括地讲,N+1 查询问题可以是这样引起的:</p>
<ul>
<li>你执行了一个单独的 SQL 语句来获取结果列表(就是“+1”)。</li>
<li>对返回的每条记录,你执行了一个查询语句来为每个加载细节(就是“N”)。</li>
</ul>
<p>使用嵌套结果方法</p>
<table>
<thead>
<tr>
<th>参数属性</th>
<th>属性信息</th>
</tr>
</thead>
<tbody>
<tr>
<td>resultMap</td>
<td>这是结果映射的 ID,可以映射关联的嵌套结果到一个合适的对象图中。这 是一种替代方法来调用另外一个查询语句。这允许你联合多个表来合成到 resultMap 一个单独的结果集。这样的结果集可能包含重复,数据的重复组需要被分 解,合理映射到一个嵌套的对象图。为了使它变得容易,MyBatis 让你“链 接”结果映射,来处理嵌套结果。一个例子会很容易来仿照,这个表格后 面也有一个示例。</td>
</tr>
<tr>
<td>columnPrefix</td>
<td>当连接多表时，你将不得不使用列别名来避免ResultSet中的重复列名。指定columnPrefix允许你映射列名到一个外部的结果集中。请看后面的例子。</td>
</tr>
<tr>
<td>notNullColumn</td>
<td>默认情况下，子对象仅在至少一个列映射到其属性非空时才创建。通过对这个属性指定非空的列将改变默认行为，这样做之后Mybatis将仅在这些列非空时才创建一个子对象。可以指定多个列名，使用逗号分隔。默认值：未设置(unset)。</td>
</tr>
<tr>
<td>autoMapping</td>
<td>如果使用了，当映射结果到当前属性时，Mybatis将启用或者禁用自动映射。该属性覆盖全局的自动映射行为。 注意它对外部结果集无影响，所以在select or resultMap属性中这个是毫无意义的。默认值：未设置(unset)。</td>
</tr>
</tbody>
</table>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--嵌套查询sql--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">"selectBlog"</span> <span class="attr">resultMap</span>=<span class="string">"blogResult"</span>&gt;</span></span><br><span class="line">    select</span><br><span class="line">    B.id as blog_id,</span><br><span class="line">    B.title as blog_title,</span><br><span class="line">    B.author_id as blog_author_id,</span><br><span class="line">    A.id as author_id,</span><br><span class="line">    A.username as author_username,</span><br><span class="line">    A.password as author_password,</span><br><span class="line">    A.email as author_email,</span><br><span class="line">    A.bio as author_bio</span><br><span class="line">    from Blog B left outer join Author A on B.author_id = A.id</span><br><span class="line">    where B.id = #&#123;id&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--使用外部结果映射方法--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">resultMap</span> <span class="attr">id</span>=<span class="string">"blogResult"</span> <span class="attr">type</span>=<span class="string">"Blog"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">id</span> <span class="attr">property</span>=<span class="string">"id"</span> <span class="attr">column</span>=<span class="string">"blog_id"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"title"</span> <span class="attr">column</span>=<span class="string">"blog_title"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">association</span> <span class="attr">property</span>=<span class="string">"author"</span> <span class="attr">column</span>=<span class="string">"blog_author_id"</span> <span class="attr">javaType</span>=<span class="string">"Author"</span> <span class="attr">resultMap</span>=<span class="string">"authorResult"</span>/&gt;</span>  <span class="comment">&lt;!--mybatis 将自动的匹配结果集中相关的各种属性进行匹配-&gt;</span></span><br><span class="line"><span class="comment">&lt;/resultMap&gt;</span></span><br><span class="line"><span class="comment">&lt;resultMap id="authorResult" type="Author"&gt;</span></span><br><span class="line"><span class="comment">  &lt;id property="id" column="author_id"/&gt;</span></span><br><span class="line"><span class="comment">  &lt;result property="username" column="author_username"/&gt;</span></span><br><span class="line"><span class="comment">  &lt;result property="password" column="author_password"/&gt;</span></span><br><span class="line"><span class="comment">  &lt;result property="email" column="author_email"/&gt;</span></span><br><span class="line"><span class="comment">  &lt;result property="bio" column="author_bio"/&gt;</span></span><br><span class="line"><span class="comment">&lt;/resultMap&gt;</span></span><br><span class="line"><span class="comment">&lt;!--使用直接映射方法--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">resultMap</span> <span class="attr">id</span>=<span class="string">"blogResult"</span> <span class="attr">type</span>=<span class="string">"Blog"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">id</span> <span class="attr">property</span>=<span class="string">"id"</span> <span class="attr">column</span>=<span class="string">"blog_id"</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"title"</span> <span class="attr">column</span>=<span class="string">"blog_title"</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">association</span> <span class="attr">property</span>=<span class="string">"author"</span> <span class="attr">javaType</span>=<span class="string">"Author"</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">id</span> <span class="attr">property</span>=<span class="string">"id"</span> <span class="attr">column</span>=<span class="string">"author_id"</span>/&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"username"</span> <span class="attr">column</span>=<span class="string">"author_username"</span>/&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"password"</span> <span class="attr">column</span>=<span class="string">"author_password"</span>/&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"email"</span> <span class="attr">column</span>=<span class="string">"author_email"</span>/&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"bio"</span> <span class="attr">column</span>=<span class="string">"author_bio"</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">association</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">resultMap</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resultMap</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>使用columnPrefix进行去重操作</p>
<p>注意使用了新列CA×× 包含一个新的前缀co_</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">"selectBlog"</span> <span class="attr">resultMap</span>=<span class="string">"blogResult"</span>&gt;</span></span><br><span class="line">  select</span><br><span class="line">    B.id            as blog_id,</span><br><span class="line">    B.title         as blog_title,</span><br><span class="line">    A.id            as author_id,</span><br><span class="line">    A.username      as author_username,</span><br><span class="line">    A.password      as author_password,</span><br><span class="line">    A.email         as author_email,</span><br><span class="line">    A.bio           as author_bio,</span><br><span class="line">    CA.id           as co_author_id,</span><br><span class="line">    CA.username     as co_author_username,</span><br><span class="line">    CA.password     as co_author_password,</span><br><span class="line">    CA.email        as co_author_email,</span><br><span class="line">    CA.bio          as co_author_bio</span><br><span class="line">  from Blog B</span><br><span class="line">  left outer join Author A on B.author_id = A.id</span><br><span class="line">  left outer join Author CA on B.co_author_id = CA.id</span><br><span class="line">  where B.id = #&#123;id&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>再次调用Author的resultMap将定义如下：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">resultMap</span> <span class="attr">id</span>=<span class="string">"authorResult"</span> <span class="attr">type</span>=<span class="string">"Author"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">id</span> <span class="attr">property</span>=<span class="string">"id"</span> <span class="attr">column</span>=<span class="string">"author_id"</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"username"</span> <span class="attr">column</span>=<span class="string">"author_username"</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"password"</span> <span class="attr">column</span>=<span class="string">"author_password"</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"email"</span> <span class="attr">column</span>=<span class="string">"author_email"</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"bio"</span> <span class="attr">column</span>=<span class="string">"author_bio"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resultMap</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>因为结果中的列名与resultMap中的列名不同。 你需要指定columnPrefix去重用映射co-author结果的resultMap。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">resultMap</span> <span class="attr">id</span>=<span class="string">"blogResult"</span> <span class="attr">type</span>=<span class="string">"Blog"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">id</span> <span class="attr">property</span>=<span class="string">"id"</span> <span class="attr">column</span>=<span class="string">"blog_id"</span> /&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"title"</span> <span class="attr">column</span>=<span class="string">"blog_title"</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">association</span> <span class="attr">property</span>=<span class="string">"author"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">resultMap</span>=<span class="string">"authorResult"</span> /&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">association</span> <span class="attr">property</span>=<span class="string">"coAuthor"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">resultMap</span>=<span class="string">"authorResult"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">columnPrefix</span>=<span class="string">"co_"</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resultMap</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h3 id="集合collection一对多关联"><a href="#集合collection一对多关联" class="headerlink" title="集合collection一对多关联"></a>集合collection一对多关联</h3><p>和一对一关联的唯一差别就是有一个oftype属性，这个属性表示的List<xxx>中xxx的类型</xxx></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">"selectBlog"</span> <span class="attr">resultMap</span>=<span class="string">"blogResult"</span>&gt;</span></span><br><span class="line">    select</span><br><span class="line">    B.id as blog_id,</span><br><span class="line">    B.title as blog_title,</span><br><span class="line">    B.author_id as blog_author_id,</span><br><span class="line">    P.id as post_id,</span><br><span class="line">    P.subject as post_subject,</span><br><span class="line">    P.body as post_body,</span><br><span class="line">    from Blog B</span><br><span class="line">    left outer join Post P on B.id = P.blog_id</span><br><span class="line">    where B.id = #&#123;id&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--内部链接写法--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">resultMap</span> <span class="attr">id</span>=<span class="string">"blogResult"</span> <span class="attr">type</span>=<span class="string">"Blog"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">id</span> <span class="attr">property</span>=<span class="string">"id"</span> <span class="attr">column</span>=<span class="string">"blog_id"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"title"</span> <span class="attr">column</span>=<span class="string">"blog_title"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">collection</span> <span class="attr">property</span>=<span class="string">"posts"</span> <span class="attr">ofType</span>=<span class="string">"Post"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">id</span> <span class="attr">property</span>=<span class="string">"id"</span> <span class="attr">column</span>=<span class="string">"post_id"</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"subject"</span> <span class="attr">column</span>=<span class="string">"post_subject"</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"body"</span> <span class="attr">column</span>=<span class="string">"post_body"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">collection</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resultMap</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--外部链接写法--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">resultMap</span> <span class="attr">id</span>=<span class="string">"blogResult"</span> <span class="attr">type</span>=<span class="string">"Blog"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">id</span> <span class="attr">property</span>=<span class="string">"id"</span> <span class="attr">column</span>=<span class="string">"blog_id"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"title"</span> <span class="attr">column</span>=<span class="string">"blog_title"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">collection</span> <span class="attr">property</span>=<span class="string">"posts"</span> <span class="attr">ofType</span>=<span class="string">"Post"</span> <span class="attr">resultMap</span>=<span class="string">"blogPostResult"</span> <span class="attr">columnPrefix</span>=<span class="string">"post_"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resultMap</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">resultMap</span> <span class="attr">id</span>=<span class="string">"blogPostResult"</span> <span class="attr">type</span>=<span class="string">"Post"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">id</span> <span class="attr">property</span>=<span class="string">"id"</span> <span class="attr">column</span>=<span class="string">"id"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"subject"</span> <span class="attr">column</span>=<span class="string">"subject"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"body"</span> <span class="attr">column</span>=<span class="string">"body"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resultMap</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>最后一定要注意一点无论是一对一还是一对多一定要写 主键关联 否则将会导致整个结果集扫描进行属性关联，严重降低性能</p>
<h3 id="鉴别器"><a href="#鉴别器" class="headerlink" title="鉴别器"></a>鉴别器</h3><p>有时一个单独的数据库查询也许返回很多不同 (但是希望有些关联) 数据类型的结果集。 鉴别器元素就是被设计来处理这个情况的, 还有包括类的继承层次结构。 鉴别器非常容易理 解,因为它的表现很像 Java 语言中的 switch 语句。</p>
<p>同上面的例子</p>
<p>使用外部关联版</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">resultMap</span> <span class="attr">id</span>=<span class="string">"vehicleResult"</span> <span class="attr">type</span>=<span class="string">"Vehicle"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">id</span> <span class="attr">property</span>=<span class="string">"id"</span> <span class="attr">column</span>=<span class="string">"id"</span> /&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"vin"</span> <span class="attr">column</span>=<span class="string">"vin"</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"year"</span> <span class="attr">column</span>=<span class="string">"year"</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"make"</span> <span class="attr">column</span>=<span class="string">"make"</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"model"</span> <span class="attr">column</span>=<span class="string">"model"</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"color"</span> <span class="attr">column</span>=<span class="string">"color"</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">discriminator</span> <span class="attr">javaType</span>=<span class="string">"int"</span> <span class="attr">column</span>=<span class="string">"vehicle_type"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">case</span> <span class="attr">value</span>=<span class="string">"1"</span> <span class="attr">resultMap</span>=<span class="string">"carResult"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">case</span> <span class="attr">value</span>=<span class="string">"2"</span> <span class="attr">resultMap</span>=<span class="string">"truckResult"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">case</span> <span class="attr">value</span>=<span class="string">"3"</span> <span class="attr">resultMap</span>=<span class="string">"vanResult"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">case</span> <span class="attr">value</span>=<span class="string">"4"</span> <span class="attr">resultMap</span>=<span class="string">"suvResult"</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">discriminator</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resultMap</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--添加结果相关的映射--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">resultMap</span> <span class="attr">id</span>=<span class="string">"carResult"</span> <span class="attr">type</span>=<span class="string">"Car"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"doorCount"</span> <span class="attr">column</span>=<span class="string">"door_count"</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resultMap</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>结合版</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">resultMap</span> <span class="attr">id</span>=<span class="string">"vehicleResult"</span> <span class="attr">type</span>=<span class="string">"Vehicle"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">id</span> <span class="attr">property</span>=<span class="string">"id"</span> <span class="attr">column</span>=<span class="string">"id"</span> /&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"vin"</span> <span class="attr">column</span>=<span class="string">"vin"</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"year"</span> <span class="attr">column</span>=<span class="string">"year"</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"make"</span> <span class="attr">column</span>=<span class="string">"make"</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"model"</span> <span class="attr">column</span>=<span class="string">"model"</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"color"</span> <span class="attr">column</span>=<span class="string">"color"</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">discriminator</span> <span class="attr">javaType</span>=<span class="string">"int"</span> <span class="attr">column</span>=<span class="string">"vehicle_type"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">case</span> <span class="attr">value</span>=<span class="string">"1"</span> <span class="attr">resultType</span>=<span class="string">"carResult"</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"doorCount"</span> <span class="attr">column</span>=<span class="string">"door_count"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">case</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">case</span> <span class="attr">value</span>=<span class="string">"2"</span> <span class="attr">resultType</span>=<span class="string">"truckResult"</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"boxSize"</span> <span class="attr">column</span>=<span class="string">"box_size"</span> /&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"extendedCab"</span> <span class="attr">column</span>=<span class="string">"extended_cab"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">case</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">case</span> <span class="attr">value</span>=<span class="string">"3"</span> <span class="attr">resultType</span>=<span class="string">"vanResult"</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"powerSlidingDoor"</span> <span class="attr">column</span>=<span class="string">"power_sliding_door"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">case</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">case</span> <span class="attr">value</span>=<span class="string">"4"</span> <span class="attr">resultType</span>=<span class="string">"suvResult"</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">"allWheelDrive"</span> <span class="attr">column</span>=<span class="string">"all_wheel_drive"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">case</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">discriminator</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resultMap</span>&gt;</span></span><br></pre></td></tr></table></figure>
          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2018/10/09/深入理解jvm虚拟机-垃圾回收/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="kyssion">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="kyssion-blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2018/10/09/深入理解jvm虚拟机-垃圾回收/" itemprop="url">未命名</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-10-09T15:22:37+08:00">
                2018-10-09
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h3 id="1-垃圾回收算法"><a href="#1-垃圾回收算法" class="headerlink" title="1.垃圾回收算法"></a>1.垃圾回收算法</h3><p><strong>技术类型：</strong></p>
<ol>
<li>引用技术法</li>
</ol>
<p>问题存在循环引用的问题</p>
<ol start="2">
<li>可达性分析算法</li>
</ol>
<p>通过引用进行遍历搜索形成一张引用关系图，将图外的内存进行回收</p>
<h3 id="1-相关算法"><a href="#1-相关算法" class="headerlink" title="1.相关算法"></a>1.相关算法</h3><h4 id="（1）标记清除算法"><a href="#（1）标记清除算法" class="headerlink" title="（1）标记清除算法"></a>（1）标记清除算法</h4><p><img src="/blogimg/jvm/2.png" alt=""></p>
<ul>
<li>老年代有应用<h4 id="（2）复制算法"><a href="#（2）复制算法" class="headerlink" title="（2）复制算法"></a>（2）复制算法</h4></li>
</ul>
<p><img src="/blogimg/jvm/3.png" alt=""></p>
<ul>
<li>主要用在新生代，发生gc的时候将Eden区的数据转移到surver区</li>
</ul>
<h4 id="（3）标记整理算法"><a href="#（3）标记整理算法" class="headerlink" title="（3）标记整理算法"></a>（3）标记整理算法</h4><p><img src="/blogimg/jvm/4.png" alt=""></p>
<ul>
<li>主要用在老年代思想就是标记+移动</li>
</ul>
<h4 id="（4）分代收集算法"><a href="#（4）分代收集算法" class="headerlink" title="（4）分代收集算法"></a>（4）分代收集算法</h4><p>针对不同的区域使用合适的<strong>垃圾回收算法  新生代 – 复制算法  老年代-标记清楚或者标记整理</strong></p>
<p>当前商业虚拟机的垃圾收集都采用“分代收集”(Generational Collection)算法,这种算法并没有什么新的思想,只是根据对象存活周期的不同将内存划分为几块。一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用<strong>“标记—清理”</strong>或者<strong>“标记—整理”</strong>算法来进行回收。</p>
<h3 id="2-java的引用类型"><a href="#2-java的引用类型" class="headerlink" title="2.java的引用类型"></a>2.java的引用类型</h3><ul>
<li>强引用就是指在程序代码之中普遍存在的,类似“Object obj=new Object()”这类的引用,只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象。</li>
<li>软引用是用来描述一些还有用但并非必需的对象。对于软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围之中进行第二次回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常。在JDK 1.2之后,提供了SoftReference类来实现软引用。</li>
<li>弱引用也是用来描述非必需对象的,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发生之前。当垃圾收集器工作时，无论当前内存是否足够,都会回收掉只被弱引用关联的对象。在JDK1.2之后,提供了WeakReference类来实现弱引用。</li>
<li>虚引用也称为幽灵引用或者幻影引用,它是最弱的一种引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。在JDK 1.2之后,提供PhantomReference类来实现虚引用。</li>
</ul>
<h3 id="3-finilize方法"><a href="#3-finilize方法" class="headerlink" title="3.finilize方法"></a>3.finilize方法</h3><p>对象在将要被gc的时候才会被触发，可以使用这个方法进行自救行为，但是注意这个方法只能使用一次，这个对象第二次被gc的时候将不会执行这个方法</p>
<h3 id="4-垃圾收集器"><a href="#4-垃圾收集器" class="headerlink" title="4.垃圾收集器"></a>4.垃圾收集器</h3><blockquote>
<p>讨论的收集器基于JDK 1.7 Update 14之后的HotSpot虚拟机</p>
</blockquote>
<p>明确一个观点:虽然我们是在对各个收集器进行比较,但并非为了挑选出一个最好的收集器。因为直到现在为止还没有最好的收集器出现,更加没有万能的收集器,所以我们选择的只是对具体应用最合适的收集器。这点不需要多加解释就能证明:如果有一种放之四海皆准、任何场景下都适用的完美收集器存在,那HotSpot虚拟机就没必要实现那么多不同的收集器了。</p>
<p><img src="/blogimg/jvm/5.png" alt=""></p>
<h4 id="（1）Serial收集器（串行收集器）"><a href="#（1）Serial收集器（串行收集器）" class="headerlink" title="（1）Serial收集器（串行收集器）"></a>（1）Serial收集器（串行收集器）</h4><p>只会使用一个CPU或一条收集线程去完成垃圾收集工作,更重要的是在它进行垃圾收集时,必须暂停其他所有的工作线程,直到它收集结束</p>
<p><img src="/blogimg/jvm/6.png" alt=""></p>
<p>适合在单线成环境下进行使用，缺点性能太低</p>
<h4 id="（2）ParNew收集器（串行收集器多线程版本）"><a href="#（2）ParNew收集器（串行收集器多线程版本）" class="headerlink" title="（2）ParNew收集器（串行收集器多线程版本）"></a>（2）ParNew收集器（串行收集器多线程版本）</h4><p>CMS作为老年代的收集器,却无法与JDK 1.4.0中已经存在的新生代收集器<br>Parallel Scavenge配合工作 ,所以在JDK 1.5中使用CMS来收集老年代的时候,新生代只能选择ParNew或者Serial收集器中的一个是许多运行在Server模式下的虚拟机中首选的新生代收集器,其中有一个与性能无关但很重要的原因是,除了Serial收集器外,目前只有它能与CMS收集器配合工作</p>
<h4 id="（3）Parallel-Scavenge收集器"><a href="#（3）Parallel-Scavenge收集器" class="headerlink" title="（3）Parallel Scavenge收集器"></a>（3）Parallel Scavenge收集器</h4><p>特点是它的关注点与其他收集器不同,CMS等收集器的关注点是尽可能地缩短垃圾收集时用户线程的停顿时间,而Parallel Scavenge收集器的目标则是达到一个可控制的吞吐量(Throughput)</p>
<h4 id="（4）serial-old"><a href="#（4）serial-old" class="headerlink" title="（4）serial old"></a>（4）serial old</h4><p>相当于serial收集器的老年代版本</p>
<h4 id="（5）parold"><a href="#（5）parold" class="headerlink" title="（5）parold"></a>（5）parold</h4><p>相当于parnew 收集器的老年代版本</p>
<h4 id="（6）CMS收集器"><a href="#（6）CMS收集器" class="headerlink" title="（6）CMS收集器"></a>（6）CMS收集器</h4><p>CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。目前很大一部分的Java应用集中在互联网站或者B/S系统的服务端上,这类应用尤其重视服务的响应速度,希望系统停顿时间最短,以给用户带来较好的体验。</p>
<p><img src="/blogimg/jvm/7.png" alt=""></p>
<p><strong>特点：</strong></p>
<ol>
<li>绝大部分新生成的对象都放在Eden区，当Eden区将满，JVM会因申请不到内存，而触发Young GC ,进行Eden区+有对象的Survivor区(设为S0区)垃圾回收，把存活的对象用复制算法拷贝到一个空的Survivor(S1)中，此时Eden区被清空，另外一个Survivor S0也为空。下次触发Young GC回收Eden+S0，将存活对象拷贝到S1中。新生代垃圾回收简单、粗暴、高效。</li>
<li>若发现Survivor区满了，则将这些对象拷贝到old区或者Survivor没满但某些对象足够Old,也拷贝到Old区(每次Young GC都会使Survivor区存活对象值+1，直到阈值)。 3.Old区也会进行垃圾收集(Young GC),发生一次 Major GC 至少伴随一次Young GC，一般比Young GC慢十倍以上。</li>
<li><p>JVM在Old区申请不到内存，会进行Full GC。Old区使用一般采用Concurrent-Mark–Sweep策略回收内存。<br><strong>缺点：</strong></p>
</li>
<li><p>GC过程中会出现STW(Stop-The-World)，若Old区对象太多，STW耗费大量时间。</p>
</li>
<li>CMS收集器对CPU资源很敏感。</li>
<li>CMS收集器无法处理浮动垃圾，可能出现“Concurrent Mode Failure”失败而导致另一次Full GC的产生。</li>
<li>CMS导致内存碎片问题。</li>
</ol>
<h4 id="（7）g1垃圾回收"><a href="#（7）g1垃圾回收" class="headerlink" title="（7）g1垃圾回收"></a>（7）g1垃圾回收</h4><p>在G1中，堆被划分成 许多个连续的区域(region)。每个区域大小相等，在1M~32M之间。JVM最多支持2000个区域，可推算G1能支持的最大内存为2000*32M=62.5G。区域(region)的大小在JVM初始化的时候决定，也可以用-<strong>XX:G1HeapReginSize设置。</strong></p>
<p>在G1中没有物理上的Yong(Eden/Survivor)/Old Generation，它们是逻辑的，使用一些非连续的区域(Region)组成的。</p>
<blockquote>
<p>新生代收集</p>
</blockquote>
<p>G1的新生代收集跟ParNew类似，当新生代占用达到一定比例的时候，开始出发收集。</p>
<p><img src="/blogimg/jvm/8.png" alt=""></p>
<p><img src="/blogimg/jvm/9.png" alt=""></p>
<p>被圈起的绿色部分为新生代的区域(region)，经过Young GC后存活的对象被复制到一个或者多个区域空闲中，这些被填充的区域将是新的新生代；当新生代对象的年龄(逃逸过一次Young GC年龄增加１)已经达到某个阈值(ParNew默认15)，被复制到老年代的区域中。</p>
<p>回收过程是停顿的(STW,Stop-The-Word);回收完成之后根据Young GC的统计信息调整Eden和Survivor的大小，有助于合理利用内存，提高回收效率。</p>
<p>回收的过程多个回收线程并发收集。</p>
<blockquote>
<p>老年代收集</p>
</blockquote>
<p><strong>和CMS类似，G1收集器收集老年代对象会有短暂停顿。</strong></p>
<ol>
<li>标记阶段，首先初始标记(Initial-Mark),这个阶段是停顿的(Stop the World Event)，并且会触发一次普通Mintor GC。对应GC log:GC pause (young) (inital-mark)</li>
<li>Root Region Scanning，程序运行过程中会回收survivor区(存活到老年代)，这一过程必须在young GC之前完成。</li>
<li>Concurrent Marking，在整个堆中进行并发标记(和应用程序并发执行)，此过程可能被young GC中断。在并发标记阶段，若发现区域对象中的所有对象都是垃圾，那个这个区域会被立即回收(图中打X)。同时，并发标记过程中，会计算每个区域的对象活性(区域中存活对象的比例)。</li>
</ol>
<p><img src="/blogimg/jvm/9.jpg" alt=""></p>
<ol start="4">
<li>Remark, 再标记，会有短暂停顿(STW)。再标记阶段是用来收集 并发标记阶段 产生新的垃圾(并发阶段和应用程序一同运行)；G1中采用了比CMS更快的初始快照算法:snapshot-at-the-beginning (SATB)。</li>
<li>Copy/Clean up，多线程清除失活对象，会有STW。G1将回收区域的存活对象拷贝到新区域，清除Remember Sets，并发清空回收区域并把它返回到空闲区域链表中。</li>
</ol>
<p><img src="/blogimg/jvm/10.jpg" alt=""></p>
<ol start="6">
<li>复制/清除过程后。回收区域的活性对象已经被集中回收到深蓝色和深绿色区域。</li>
</ol>
<p><img src="/blogimg/jvm/11.jpg" alt=""></p>
<p><strong>关于Remembered Set概念</strong>：G1收集器中，Region之间的对象引用以及其他收集器中的新生代和老年代之间的对象引用是使用Remembered Set来避免扫描全堆。G1中每个Region都有一个与之对应的Remembered Set，虚拟机发现程序对Reference类型数据进行写操作时，会产生一个Write Barrier暂时中断写操作，检查Reference引用的对象是否处于不同的Region之间(在分代中例子中就是检查是否老年代中的对象引用了新生代的对象)，如果是便通过CardTable把相关引用信息记录到被引用对象所属的Region的Remembered Set中。当内存回收时，在GC根节点的枚举范围加入Remembered Set即可保证不对全局堆扫描也不会有遗漏。</p>
<p>G1虽然保留了CMS关于代的概念，但是代已经不是物理上连续区域，而是一个逻辑的概念。在标记过程中，每个区域的对象活性都被计算，在回收时候，就可以根据用户设置的停顿时间，选择活性较低的区域收集，这样既能保证垃圾回收，又能保证停顿时间，而且也不会降低太多的吞吐量。Remark阶段新算法的运用，以及收集过程中的压缩，都弥补了CMS不足。引用Oracle官网的一句话：“G1 is planned as the long term replacement for the Concurrent Mark-Sweep Collector (CMS)”。</p>

          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2018/10/09/深入理解jvm虚拟机-内存划分方法/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="kyssion">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="kyssion-blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2018/10/09/深入理解jvm虚拟机-内存划分方法/" itemprop="url">未命名</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-10-09T15:22:37+08:00">
                2018-10-09
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h3 id="一-运行时的数据区域"><a href="#一-运行时的数据区域" class="headerlink" title="一.运行时的数据区域"></a>一.运行时的数据区域</h3><p><img src="/blogimg/jvm/1.png" alt=""></p>
<h4 id="（1）程序计数器"><a href="#（1）程序计数器" class="headerlink" title="（1）程序计数器"></a>（1）程序计数器</h4><p>程序计数器(Program Counter Register)是一块较小的内存空间,它可以看作是当前线程所执行的字节码的<strong>行号指示器</strong>—–编译原理中指向下一条指令的位置</p>
<p>Java虚拟机的多线程是通过线程<strong>轮流切换并分配处理器执行时间</strong>的方式来实现的，每条线程都需要有一个<strong>独立的程序计数器</strong>,各条线程之间计数器<strong>互不影响</strong>,独立存储,我们称这类内存区域为“线程私有”的内存</p>
<p><strong>注意：</strong></p>
<ul>
<li>如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址</li>
<li>如果正在执行的是Native方法,这个计数器值则为空(Undefined)</li>
</ul>
<h4 id="（2）Java虚拟机栈"><a href="#（2）Java虚拟机栈" class="headerlink" title="（2）Java虚拟机栈"></a>（2）Java虚拟机栈</h4><p>Java虚拟机栈(Java Virtual Machine Stacks)也是线程私有的,它的<strong>生命周期与线程相同</strong>。</p>
<p>虚拟机栈描述的是Java方法执行的内存模型:<strong>每个方法在执行的同时都会创建一个栈帧</strong>(Stack Frame )用于<strong>存储局部变量表</strong>、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。</p>
<p>局部变量表存放了编译期可知的各种基本数据类型、对象引用（<strong>reference字段</strong>）和了一条字节码指令的地址，方法的开始</p>
<p>一个重要的异常 <strong>stackOverflowError  当内存不够的时候抛出 OutofMenoryError</strong></p>
<h4 id="（3）本地方法栈区"><a href="#（3）本地方法栈区" class="headerlink" title="（3）本地方法栈区"></a>（3）本地方法栈区</h4><p>和虚拟机栈相似值不过使用的是native的方法服务</p>
<blockquote>
<p>栈区大小使用 -Xss进行配置     </p>
</blockquote>
<blockquote>
<p>引申：参数 -XX：PermSize  -XX ：MaxPermSize  — 指定非堆内存的最大容量</p>
</blockquote>
<h4 id="（4）java堆"><a href="#（4）java堆" class="headerlink" title="（4）java堆"></a>（4）java堆</h4><p>Java堆(Java Heap)是Java虚拟机所管理的内存中最大的一块。Java堆是<strong>被所有线程共享的一块内存区域,在虚拟机启动时创建，用来存放对象实例</strong></p>
<p>指定java堆大小的参数 -Xms  -Xmx  –最大值和最小值</p>
<h4 id="（5）方法区"><a href="#（5）方法区" class="headerlink" title="（5）方法区"></a>（5）方法区</h4><p>所有<strong>线程共享，存储常量静态常量，编译后的各种代码</strong>等数据</p>
<blockquote>
<p>运行时常量池-方法区的一部分用来储存java的class类的各种其他信息</p>
</blockquote>
<h4 id="（6）额外部分-直接内存使用’"><a href="#（6）额外部分-直接内存使用’" class="headerlink" title="（6）额外部分 直接内存使用’"></a>（6）额外部分 直接内存使用’</h4><p>当java使用NIO的时候，直接使用外部内存而不是使用 虚拟机的虚拟内存</p>

          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
  </section>

  
  <nav class="pagination">
    <a class="extend prev" rel="prev" href="/"><i class="fa fa-angle-left"></i></a><a class="page-number" href="/">1</a><span class="page-number current">2</span><a class="page-number" href="/page/3/">3</a><span class="space">&hellip;</span><a class="page-number" href="/page/14/">14</a><a class="extend next" rel="next" href="/page/3/"><i class="fa fa-angle-right"></i></a>
  </nav>



          </div>
          


          

        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      

      <section class="site-overview-wrap sidebar-panel sidebar-panel-active">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <p class="site-author-name" itemprop="name">kyssion</p>
              <p class="site-description motion-element" itemprop="description"></p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/archives/">
              
                  <span class="site-state-item-count">133</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                
                  <span class="site-state-item-count">3</span>
                  <span class="site-state-item-name">分类</span>
                
              </div>
            

            
              
              
              <div class="site-state-item site-state-tags">
                
                  <span class="site-state-item-count">2</span>
                  <span class="site-state-item-name">标签</span>
                
              </div>
            

          </nav>

          

          

          
          

          
          

          

        </div>
      </section>

      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2018</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">kyssion</span>

  
</div>


  <div class="powered-by">由 <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a> 强力驱动</div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">主题 &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Mist</a> v5.1.4</div>




        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  
    <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.4"></script>



  
  

  

  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  












  





  

  

  

  
  

  

  

  

</body>
</html>
